Draw the life cycle of thread diagram and explain it with example.

Java Thread Life Cycle: Diagram and Example (B.Tech CSE, 5th Semester)

In Java, every thread moves through well-defined states from creation to completion. Understanding the thread life cycle helps you write correct, efficient, and thread-safe programs. Below is a clear diagram and a simple example to visualize how a thread transitions between states.

Thread Life Cycle Diagram (States and Transitions)

States in Java (java.lang.Thread.State):
  NEW
  RUNNABLE
  BLOCKED
  WAITING
  TIMED_WAITING
  TERMINATED

ASCII Diagram:
  [NEW] --start()----------------------------------------> [RUNNABLE]
                       |                                       |
                       | CPU assigned (ready/running)          |
                       |                                       |
                       |-- cannot get monitor/lock ----------> [BLOCKED]
                       |                                       |
                       |<-- lock acquired ---------------------|
                       |
                       |-- wait() / join() (no timeout) ----> [WAITING]
                       |                                       |
                       |<-- notify()/notifyAll() / target ends-|
                       |
                       |-- sleep(t) / wait(t) / join(t) ----> [TIMED_WAITING]
                       |                                       |
                       |<-- time expires ----------------------|
                       |
                       |-- run() completes ------------------> [TERMINATED]

Notes:
- RUNNABLE in Java includes both "ready" and "running" (there is no separate RUNNING state).
- BLOCKED occurs when a thread tries to enter a synchronized block but the monitor is held by another thread.
- WAITING means waiting indefinitely; TIMED_WAITING means waiting with a timeout.

States Explained in Simple Terms

  • NEW: Thread object is created but start() not called yet.
  • RUNNABLE: Thread is ready to run or actually running on the CPU.
  • BLOCKED: Waiting to acquire a monitor/lock to enter a synchronized block/method.
  • WAITING: Waiting indefinitely for another thread’s action (e.g., wait(), join() without timeout).
  • TIMED_WAITING: Paused for a specified time (e.g., sleep(ms), wait(ms), join(ms)).
  • TERMINATED: Thread’s run() method finished (normal or due to uncaught exception).

Java Example: Observe Thread States in Action

This program creates four threads to demonstrate TIMED_WAITING, BLOCKED, and WAITING, and prints their states as they change.

// File: ThreadLifeCycleDemo.java
public class ThreadLifeCycleDemo {

    static final Object LOCK = new Object();

    public static void main(String[] args) throws Exception {
        // 1) Will go to TIMED_WAITING via sleep()
        Thread tSleep = new Thread(() -> {
            try { Thread.sleep(1000); } catch (InterruptedException ignored) {}
        }, "Sleeper");

        // 2) Holds the LOCK for a while
        Thread tLock = new Thread(() -> {
            synchronized (LOCK) {
                try { Thread.sleep(1200); } catch (InterruptedException ignored) {}
            }
        }, "LockHolder");

        // 3) Tries to enter synchronized block while LockHolder holds it -> BLOCKED
        Thread tBlocked = new Thread(() -> {
            synchronized (LOCK) {
                busyWork(300); // runs after lock becomes available
            }
        }, "BlockedOnLock");

        // 4) WAITING: This thread waits for LockHolder to finish using join()
        Thread tJoiner = new Thread(() -> {
            try { tLock.join(); } catch (InterruptedException ignored) {}
        }, "Joiner");

        // Initial states: all NEW
        System.out.println(tSleep.getName()   + " -> " + tSleep.getState());
        System.out.println(tLock.getName()    + " -> " + tLock.getState());
        System.out.println(tBlocked.getName() + " -> " + tBlocked.getState());
        System.out.println(tJoiner.getName()  + " -> " + tJoiner.getState());
        System.out.println("--- starting threads ---");

        // Start in a sequence that creates clear states
        tLock.start();           // Grabs LOCK and sleeps
        Thread.sleep(50);        // Give LockHolder time to acquire lock
        tBlocked.start();        // Will be BLOCKED on LOCK
        tSleep.start();          // Will go to TIMED_WAITING (sleep)
        tJoiner.start();         // Will WAIT for LockHolder to finish

        // Monitor: print states periodically until all finish
        Thread monitor = new Thread(() -> {
            Thread[] arr = { tLock, tBlocked, tSleep, tJoiner };
            boolean anyAlive;
            do {
                anyAlive = false;
                for (Thread t : arr) {
                    System.out.println(t.getName() + " -> " + t.getState());
                    if (t.isAlive()) anyAlive = true;
                }
                System.out.println("---");
                try { Thread.sleep(200); } catch (InterruptedException ignored) {}
            } while (anyAlive);

            // Final states: TERMINATED
            for (Thread t : new Thread[]{tLock, tBlocked, tSleep, tJoiner}) {
                System.out.println(t.getName() + " -> " + t.getState());
            }
        }, "Monitor");

        monitor.start();
        monitor.join();
    }

    static void busyWork(long ms) {
        long end = System.currentTimeMillis() + ms;
        while (System.currentTimeMillis() < end) {
            // simple CPU work
        }
    }
}

What This Example Demonstrates

  • Sleeper goes to TIMED_WAITING due to Thread.sleep(1000).
  • LockHolder enters RUNNABLE then holds a monitor (inside synchronized) and sleeps.
  • BlockedOnLock becomes BLOCKED until LockHolder releases the monitor.
  • Joiner becomes WAITING because it called join() on LockHolder.
  • All threads eventually reach TERMINATED when their run() methods complete.

Key Takeaways for Exams

  • Java defines six thread states: NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED.
  • start() moves a thread from NEW to RUNNABLE; finishing run() moves it to TERMINATED.
  • synchronized can cause BLOCKED; wait()/join() cause WAITING; sleep() causes TIMED_WAITING.
  • RUNNABLE covers both ready and running; the scheduler decides when a RUNNABLE thread actually runs.