Thread Lifecycle

Thread States

Thread.getState() returns one of six states from the Thread.State enum.

start()
  NEW ──────────────► RUNNABLE ◄────────────────────────┐
                        │  │  │                         │
     waiting for lock   │  │  │ wait(), join(), park()  │ notify / lock free /
           ┌────────────┘  │  └──────────┐              │ timeout / unpark
           ▼               │             ▼              │
        BLOCKED            │     WAITING / TIMED_WAITING ┘
                           │     (sleep(ms), wait(ms))
                           ▼ run() ends
                      TERMINATED
StateMeaning
NEWcreated, start() not called yet
RUNNABLErunning or ready to run (waiting for a CPU)
BLOCKEDwaiting to enter a synchronized block held by another thread
WAITINGwaiting with no timeout: wait(), join(), LockSupport.park()
TIMED_WAITINGsleep(ms), wait(ms), join(ms)
TERMINATEDrun() finished (normally or with an exception)

Watching the States

Example

The main thread waits until the worker reaches each state before printing it, so the output is always the same.

import java.util.concurrent.CountDownLatch;

public class Main {
    public static void main(String[] args) throws Exception {
        CountDownLatch gate = new CountDownLatch(1);
        Object lock = new Object();

        Thread worker = new Thread(() -> {
            try { gate.await(); } catch (InterruptedException e) { return; }
            synchronized (lock) { }               // will be BLOCKED while main holds the lock
        });
        System.out.println("After new:   " + worker.getState());

        worker.start();
        waitFor(worker, Thread.State.WAITING);
        System.out.println("Awaiting:    " + worker.getState());

        synchronized (lock) {
            gate.countDown();
            waitFor(worker, Thread.State.BLOCKED);
            System.out.println("Lock busy:   " + worker.getState());
        }
        worker.join();
        System.out.println("After join:  " + worker.getState());
    }

    static void waitFor(Thread t, Thread.State s) {
        while (t.getState() != s) Thread.onSpinWait();
    }
}

Output

After new:   NEW
Awaiting:    WAITING
Lock busy:   BLOCKED
After join:  TERMINATED

Interrupting a Thread

Example

interrupt() politely asks a thread to stop. A sleeping or waiting thread gets an InterruptedException; a running thread should check isInterrupted().

public class Main {
    public static void main(String[] args) throws InterruptedException {
        Thread downloader = new Thread(() -> {
            try {
                System.out.println("Downloading... (sleeping 10 s)");
                Thread.sleep(10_000);
                System.out.println("Done");
            } catch (InterruptedException e) {
                System.out.println("Cancelled by user, cleaning up");
            }
        });
        downloader.start();
        while (downloader.getState() != Thread.State.TIMED_WAITING) Thread.onSpinWait();
        downloader.interrupt();
        downloader.join();
        System.out.println("Main finished, worker state: " + downloader.getState());
    }
}

Output

Downloading... (sleeping 10 s)
Cancelled by user, cleaning up
Main finished, worker state: TERMINATED