How to Create a Thread in Java
There are two classic ways to create a thread in Java: extend the Thread class and override its run() method, or implement the Runnable interface and pass the object to a Thread. Because Runnable is a functional interface, the second way is usually written as a lambda. In every case, the thread begins running only when you call start(). Since Java 21, the Thread.Builder API (Thread.ofPlatform() and Thread.ofVirtual()) offers a third, modern style. In this lesson, you will learn each way with examples.
Ways to Create a Thread
| Way | Code |
|---|---|
Extend Thread | class Worker extends Thread { public void run() { ... } } |
Implement Runnable | new Thread(new MyTask()) |
Lambda (a Runnable) | new Thread(() -> ...) |
| Thread builder (Java 21) | Thread.ofPlatform().name("w").start(() -> ...) |
Thread Constructors
| Constructor | Description |
|---|---|
Thread() | It is used when a subclass overrides run(). |
Thread(Runnable task) | It creates a thread that runs the task. |
Thread(Runnable task, String name) | It also gives the thread a name. |
Thread(String name) | It creates a named thread (for subclasses). |
Example: Extending Thread
Let's see an example of the first way.
public class ExtendThread {
static class Greeter extends Thread {
private final String who;
Greeter(String who) {
this.who = who;
}
@Override
public void run() {
System.out.println("Hello, " + who + " from " + getName());
}
}
public static void main(String[] args) throws InterruptedException {
Greeter g = new Greeter("Navika");
g.setName("greeter-1");
g.start();
g.join();
System.out.println("Main finished");
}
}Hello, Navika from greeter-1
Main finishedExplanation: Greeter extends Thread and overrides run(), which holds the work. start() creates the new thread, which then calls run(). join() waits for it so the main thread's message comes last.
Example: Runnable and Lambdas
public class RunnableWays {
static class Counter implements Runnable {
@Override
public void run() {
System.out.println("Counter running in "
+ Thread.currentThread().getName());
}
}
public static void main(String[] args) throws InterruptedException {
Thread a = new Thread(new Counter(), "counter");
Thread b = new Thread(() -> System.out.println("Lambda running in "
+ Thread.currentThread().getName()), "lambda");
Thread c = Thread.ofPlatform().name("built").unstarted(
() -> System.out.println("Builder thread "
+ Thread.currentThread().getName()));
a.start();
a.join();
b.start();
b.join();
c.start();
c.join();
}
}Counter running in counter
Lambda running in lambda
Builder thread builtExplanation: Counter implements Runnable; a Thread runs it. The lambda is a Runnable too, written inline. Thread.ofPlatform().name(...).unstarted(...) builds a named thread without starting it. Each thread is joined before the next starts, so the output order is fixed.
Threads in Real Applications
Common Mistakes
Calling run() instead of start(). The work runs in the current thread (see "Calling Thread.run() Directly vs Thread.start()").
Extending Thread just to run a task. Your class then can't extend anything else; use Runnable.
Forgetting to join() before reading a thread's results. The thread may not have finished yet.
Interview Corner
What are the ways to create a thread in Java?
Extend java.lang.Thread and override run(), or implement Runnable (often as a lambda) and pass it to a Thread constructor; in both cases call start() to begin execution. Since Java 21, Thread.ofPlatform() and Thread.ofVirtual() builders can create platform or virtual threads. In practice, tasks are usually submitted to an ExecutorService rather than creating threads directly. A Callable can also be run through an executor when a result is needed.
Practice
- Easy: Create three threads with lambdas, each printing a different name, and join them in order.
- Harder: Write a
Runnablethat sums the numbers from 1 to a given limit and stores the result in a field; run it in a thread, join, and print the result.
Key Takeaways
Was this tutorial helpful?