How to Create a Thread in Java

Naveen AnamaneniUpdated · 4 min read

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

WayCode
Extend Threadclass Worker extends Thread { public void run() { ... } }
Implement Runnablenew Thread(new MyTask())
Lambda (a Runnable)new Thread(() -> ...)
Thread builder (Java 21)Thread.ofPlatform().name("w").start(() -> ...)

Thread Constructors

ConstructorDescription
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.

ExtendThread.java▶ Try it
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");
    }
}
Output
Hello, Navika from greeter-1
Main finished

Explanation: 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

RunnableWays.java▶ Try it
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();
    }
}
Output
Counter running in counter
Lambda running in lambda
Builder thread built

Explanation: 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

  1. Easy: Create three threads with lambdas, each printing a different name, and join them in order.
  2. Harder: Write a Runnable that 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.

Quick check: Creating threads

4 questions
1Which method holds a thread's work?
2Why prefer Runnable over extending Thread?
3Is Runnable a functional interface?
4Which Java 21 API builds platform threads?

Key Takeaways

Was this tutorial helpful?

Lesson 380 of 482