Codectionary / Developer documentation / Java

Creating Threads (Thread & Runnable)

A thread is an independent path of execution within a program, letting multiple tasks run seemingly simultaneously. Java offers two main ways to create a thread: extending the Thread class directly and overriding its run() method, or implementing the Runnable interface and passing it to a Thread - the Runnable approach is generally preferred, since Java doesn't support multiple inheritance and Runnable keeps your class free to extend something else.

Syntax

Thread t = new Thread(() -> { /* task */ });\nt.start();

Examples

Extending the Thread Class

Creating a thread by subclassing Thread and overriding run().

class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 1; i <= 3; i++) {
            System.out.println("Thread running: " + i);
        }
    }
}

MyThread thread = new MyThread();
thread.start();  // starts a new thread - do NOT call run() directly

Implementing Runnable

The generally preferred approach - implement Runnable and pass it to a Thread.

class Task implements Runnable {
    @Override
    public void run() {
        for (int i = 1; i <= 3; i++) {
            System.out.println("Task running: " + i);
        }
    }
}

Thread thread = new Thread(new Task());
thread.start();

Runnable with a Lambda

Since Runnable is a functional interface, a lambda is often the most concise way to define a thread's task.

Runnable task = () -> {
    for (int i = 1; i <= 3; i++) {
        System.out.println("Lambda thread: " + i);
    }
};

Thread thread = new Thread(task);
thread.start();

// Even more concise, inline:
new Thread(() -> System.out.println("Quick task")).start();

Running Multiple Threads Concurrently

Starting several threads that run independently and roughly in parallel.

Runnable printNumbers = () -> {
    for (int i = 1; i <= 3; i++) System.out.println("Numbers: " + i);
};

Runnable printLetters = () -> {
    for (char c = 'a'; c <= 'c'; c++) System.out.println("Letters: " + c);
};

Thread t1 = new Thread(printNumbers);
Thread t2 = new Thread(printLetters);

t1.start();
t2.start();
// Output order between t1 and t2 is not guaranteed - that's the nature of concurrency

Best practices

  • Prefer implementing Runnable over extending Thread - it keeps your class free to extend another class, since Java only allows single inheritance
  • Always call start() to begin a new thread of execution - calling run() directly just executes the code on the current thread, with no concurrency at all
  • Use an ExecutorService instead of manually creating raw Thread objects for anything beyond simple examples - it manages thread lifecycles far more efficiently
  • Don't assume any particular execution order between separate threads - the operating system's scheduler decides, and it can vary between runs

Runtime & versions

Java Virtual Machine. Feature availability depends on the language and runtime version used by your project; consult the official reference below.

Java Language Specification

Specifications & further reading