Create and manage threads with Thread, Runnable, and understand the thread lifecycle.
Published February 10, 2025
A thread is the smallest unit of execution within a process. Java supports multithreading natively, allowing multiple threads to run concurrently within the same JVM process, sharing heap memory.
Option 1: Extend Thread
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("Running in: " + Thread.currentThread().getName());
}
}
new MyThread().start(); // start() creates a new OS thread and calls run()
Option 2: Implement Runnable (preferred)
Runnable task = () -> System.out.println("Task in: " + Thread.currentThread().getName());
Thread t = new Thread(task, "worker-1");
t.start();
Prefer Runnable over extending Thread — it separates the task from the thread mechanism, and a class can only extend one class.
NEW → RUNNABLE → [RUNNING] → TERMINATED
↕
BLOCKED/WAITING/TIMED_WAITING
synchronized)Object.wait(), Thread.join())Thread.sleep(ms), LockSupport.parkNanos())run() completed or threw an exceptionThread t = new Thread(() -> { /* ... */ });
System.out.println(t.getState()); // NEW
t.start();
System.out.println(t.getState()); // RUNNABLE
t.join(); // wait for completion
System.out.println(t.getState()); // TERMINATED
Thread t = new Thread(task);
t.setName("processor-1"); // useful for debugging
t.setDaemon(true); // JVM exits even if daemon threads are running
t.setPriority(Thread.MAX_PRIORITY); // 1-10, default 5 (hint only)
t.start(); // begin execution
t.join(); // wait for this thread to finish
t.join(5000); // wait max 5 seconds
t.interrupt(); // request interruption
// Check interruption
if (Thread.currentThread().isInterrupted()) {
// clean up and stop
}
// Static methods
Thread.sleep(1000); // pause current thread (throws InterruptedException)
Thread.yield(); // hint to scheduler to yield CPU
Thread.currentThread(); // reference to currently running thread
public void run() {
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // IMPORTANT: restore interrupt flag
return; // exit cleanly
}
}
Never swallow InterruptedException silently — always restore the interrupt flag or re-throw.
// UNSAFE: counter++ is not atomic (read-modify-write)
private int counter = 0;
public void increment() { counter++; } // race condition!
// SAFE: use AtomicInteger
private AtomicInteger counter = new AtomicInteger();
public void increment() { counter.incrementAndGet(); }
start() (creates new thread) and run() (executes in the calling thread — does NOT create a new thread).Thread.sleep() does NOT release locks — Object.wait() does.