Skip to content
Mayank Pant
Go back

Thread lifecycle

The collective information of a thread right from its starting point to ending point is called as “Thread Life Cycle”.

In Java applications, Threads can have the following states as part of their lifecycle:

More correct: thread-lifecycle

or more detailed:

detailed-thread-lifecycle


Lifecycle states:

New/Born State:

Ready/Runnable State:

Running State:

NOTE: We can send a thread from Running state to Ready state directly by accessing yield() method, but, it is not supported by Windows operating system, because, it will perform its functionality on the basis of Threads priority values, priority based operations are not supported by windows operating system.

Dead / Destroy / Terminated State:

stop() actually releases all locks and leads to ThreadDeathException (silent unchecked exception) which leaves objects held by the thread in an inconsistent state. This is why it’s deprecated.

Blocked State:

Waiting State:

Timed waiting state:


In Java applications, we are able to bring a thread from Blocked state to Ready / Runnable state in the following situations:

  1. When sleep time is over.
  2. If any other thread access notify() / notifyAll() methods.
  3. If any other thread access resume() method.
  4. When IO Operations are completed.

Understanding Monitor Locks

A monitor lock ensures that only one thread at a time executes a synchronized section of code on the same object.

Every Java object has an intrinsic monitor lock. When a thread enters a synchronized block or method, it attempts to acquire the lock of the object. If the lock is already held by another thread, the current thread enters the Blocked state. When the thread holding the lock exits the synchronized section, the monitor lock is released, allowing another waiting thread to acquire it.

Example: How Monitor Locks Work

class MonitorLockExample {
  synchronized void taskOne() {
    System.out.println(Thread.currentThread().getName() + " entered taskOne");
    try {
      Thread.sleep(10000); // Simulate long operation
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName() + " completed taskOne");
  }


  void taskTwo() {
    System.out.println(Thread.currentThread().getName() + " before synchronized block in taskTwo");
    synchronized (this) {
      System.out.println(Thread.currentThread().getName() + " inside synchronized block of taskTwo");
    }
  }


  void taskThree() {
    System.out.println(Thread.currentThread().getName() + " executing taskThree (no lock)");
  }


  public static void main(String[] args) {
    MonitorLockExample obj = new MonitorLockExample();


    Thread t1 = new Thread(() -> obj.taskOne(), "Thread-1");
    Thread t2 = new Thread(() -> obj.taskTwo(), "Thread-2");
    Thread t3 = new Thread(() -> obj.taskThree(), "Thread-3");
    
    
    t1.start();
    t2.start();
    t3.start();
  }
}

🧠 What Happens Here:

Each object in Java maintains its own monitor lock. If two threads operate on different objects, they can both enter synchronized methods concurrently.


wait(), notify(), and notifyAll() — Thread Communication

Java provides these methods for inter-thread communication using monitor locks:

When a thread is waiting (via wait()), it transitions to the WAITING state and releases its monitor lock. Once notified, it moves back to Runnable.


Further reading


Share this post on:

Previous Post
Generics in Java
Next Post
Multithreading MOC