These questions separate a thread's task, its Java object, and its execution. The same basic lifecycle rules apply to platform and virtual threads.
Answer: A Thread object represents a thread and exposes operations such as start, interrupt, and join. A thread of execution is the activity that executes instructions with its own execution state. Constructing a Thread does not, by itself, begin that activity.
A thread is not a separate operating-system process. Threads in the same JVM can share objects, which is why access to mutable shared state needs coordination. In Java SE 25, a platform thread is typically backed by an operating-system thread, whereas a virtual thread is scheduled by the runtime. Both are represented by Thread objects.
Answer: The JVM execution model gives each thread its own JVM stack, containing frames for method invocations. A frame holds information such as local variables and an operand stack. An implementation can manage the underlying storage differently, particularly for virtual threads, so a logical per-thread stack does not imply a permanently dedicated operating-system stack.
Separate stacks do not make referenced objects private. Two threads can each have a local variable that points to the same object. Updating that object can still introduce a data race. Distinguish a local reference, which belongs to an invocation, from the mutable object it references.
Answer: No. Main is the application's launch entry point, not the entry point for every subsequently created thread. A worker thread normally runs the Runnable task provided to it, through the Thread execution machinery. Frameworks may introduce additional frames around application code.
Do not depend on an exact bottom stack frame: launchers, executors, and JVM implementations can supply supporting frames. In Java SE 25, an application entry point can also be an eligible instance main method or a main method without arguments; the classic public static main(String[]) remains valid.
Answer: No. new Thread(task) constructs an unstarted platform thread. Call start() to schedule it. Likewise, Thread.ofVirtual().unstarted(task) creates an unstarted virtual thread, while Thread.ofVirtual().start(task) creates and starts one in a single operation.
The distinction matters when configuring a thread or publishing task inputs before execution. A thread starts at most once. Calling the task's run method directly executes it on the calling thread, without creating a new execution context or changing the lifecycle of an unstarted Thread object.
Answer: No. Starting thread A before thread B does not guarantee that A executes its task first or finishes first. Scheduling varies with the runtime, operating system, available processors, and workload. Several threads can execute simultaneously on different cores.
Express required ordering through coordination: join waits for termination, a CountDownLatch can signal a milestone, and a Future can represent a task result. These mechanisms also provide documented memory-visibility guarantees. Sleep durations, thread priorities, and observations from a few test runs do not establish a correct inter-thread dependency.
Answer: A Runnable expresses work in its void run() method, which a lambda can implement. A Thread constructed with that Runnable invokes the task when started. Alternatively, a Thread subclass can override run, although composing a Runnable with a thread or executor usually separates responsibilities more clearly.
A Callable task instead supplies call(), which can return a result and throw checked exceptions. Submit it to an appropriate executor rather than passing it directly to the Thread(Runnable) constructor. âRun is always the first stack frameâ is too literal; the runtime can place execution machinery around the task.
Answer: Supply a Runnable to new Thread(task), use a platform or virtual thread builder, or, when subclassing is justified, construct a Thread subclass. Creating a Runnable alone creates a task, not a thread.
public class StartingThreads {
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> System.out.println("Task completed");
Thread platform = new Thread(task);
platform.start();
platform.join();
Thread virtual = Thread.ofVirtual().start(task);
virtual.join();
}
}
This prints Task completed twice. Each join waits for its corresponding task to finish. Virtual threads are useful for large numbers of tasks that spend time waiting; they do not make a CPU-bound calculation intrinsically faster.
Answer: Override public void run(), with no parameters. Use @Override so the compiler catches a mistaken signature. Then invoke start on the instance to request separate execution; calling run directly is an ordinary method call.
Do not override start just to provide the task body. That method performs lifecycle work needed to start the thread. A Runnable is often preferable because it leaves the class free to extend another superclass and lets the same task abstraction work with thread builders and executors.
Answer: Start a Thread using start or a builder's start operation. You can also submit work to an executor whose documented execution policy provides worker threads. The general Executor interface alone does not promise a new or separate thread; an implementation can execute a task directly in the caller.
Starting a thread establishes a happens-before relationship: actions before start become visible to the started thread. Later shared updates still require suitable coordination. Neither calling run nor assigning a Runnable to a variable provides a substitute for starting concurrent execution.
Answer: Runnable describes what to do, while Thread or an executor determines how the work is executed. This separation makes a task easier to test directly, submit to different execution mechanisms, or reuse without coupling its business logic to Thread inheritance.
Reuse does not automatically imply thread safety. If the same Runnable instance is executed concurrently, its mutable fields may be shared by several threads. Keep task state confined to an invocation where possible, or coordinate shared access. Reusing a task is valid; restarting a previously started Thread object is not.
References: JVM stacks, Thread API, and Executor execution policies.