JB Header
Understanding Thread Life Cycle, Thread States in Java | Tutorial with Examples
This tutorial explains thread life cycle in Java with examples. This is the second article in the Java Concurrency Series, with the first articleClick to Read tutorial on Java MultiThreading Basics & How-to create/run Threads covering basics of multithreading in Java. In this tutorial we will start by looking at the Java thread lifecycle diagram. We will then look at individual thread states in detail to understand the state information they encapsulate and how transitions happen between these states. Lastly, we will take a look at a code example showing how a thread moves through its states, understand the logic of the program via a sequence diagram and then understand how the code works. Java Thread Life Cycle Let us start by getting a high level understanding of the 6 thread states in Java with the diagram shown next -
6 Thread States in Java and Thread Life Cycle
Above diagram shows how a typical thread moves through the different stages of its life cycle. Let us look at these states one-by-one and understand their place in the life of a Java thread -
  • New - A newly created thread object instance on which the start() method has not yet been invoked is in the new state. To learn how to instantiate threads in the proper way check out this tutorialClick to Read tutorial explaining how to create a Thread in Java.
  • Runnable - A thread in new state enters the runnable state when the Thread.start() method is invoked on it. There are 2 important points to note regarding the runnable state -
    1. Although the thread enters the runnable state immediately on invoking the start() method, but it is not necessary that the thread immediately starts executing. A thread runs when the logic it holds in its run() method can be executed by the processor. In case the thread logic needs any resource which is not available then the thread waits for the resource to become available.
    2. Secondly, a thread in runnable state may run for some time and then get blocked for a monitor lock, or enter the waiting/timed_waiting states as it waits for the opportunity/time to enter runnable state again.

  • Blocked - A running thread may enter the blocked state as it waits for a monitor lock to be freed. It may also be blocked as it waits to reenter a monitor lock after being asked to wait using the Thread.wait() method.
  • Waiting - A thread enters the waiting state when it is made to wait for a go-ahead signal to proceed. The go-ahead in this case is given by another thread and can be given in the following 3 scenarios -
    1. Thread waiting due to Thread.wait() method being called on it: The other thread can use Thread.notify() or Thread.notifyAll() to give the go-ahead to the waiting thread.
    2. Thread waiting as it itself has asked for joining another thread using Thread.join(): The waiting thread gets a go-ahead when the thread its waiting for ends.
    3. Thread waiting due to LockSupport.park()method being invoked on it: The waiting thread resumes when LockSupport.unPark() is called with the parked thread object as the parameter.

  • Timed_Waiting - A thread which is waiting as it has been specifically 'instructed' to wait for a specified waiting time is in a timed_waiting state. A thread can be made to wait for a pre-determined amount of time in the following ways -
    1. Thread made to wait using Thread.sleep() method.
    2. Threads being asked to wait for a permit for a specified amount of time using LockSuport.parkNanos() and LockSupport.parkUntil() methods.
    3. Threads being made to wait for a fixed amount of time using Thread.wait(long millis) or Thread.join(long millis, int nanos).

  • Terminated - A thread enters its 'final resting' state or terminated state when it has finished executing the logic specified in its run() method.
In-built Java Enum Constants for thread states To provide a standard naming and reference for individual thread states, Java language designers have defined an enum named java.lang.Thread.State which has the following constants defined (each one named after the thread state it refers to) -
  • ThreadState.BLOCKED
  • ThreadState.NEW
  • ThreadState.RUNNABLE
  • ThreadState.TERMINATED
  • ThreadState.TIMED_WAITING
  • ThreadState.WAITING
Java example showing thread states in action The Java example below shows how a typical thread moves through the various life cycle states. A sequence diagram showing interaction between threads and detailed explanation of the code follows.
Java example showing how a thread moves between different states
package com.javabrahman.corejava.threads;
public class ThreadStates {

  public static void main(String args[]){
    //Creating an instance of Basic Thread
    Thread threadInstance=new Thread(new BasicThread());
    threadInstance.start();
    System.out.println("BasicThread State: "+threadInstance.getState());
    try {
      boolean keepRunning=true;
      int count=1;
      while(keepRunning) {
        Thread.sleep(2000);
        System.out.println(count*2+ " Seconds elapsed - BasicThread State: "+threadInstance.getState());
        count++;
        if(count==4){
          //6 seconds elapsed
          synchronized(threadInstance) {
          threadInstance.notify();
         }
        }
        if(Thread.State.TERMINATED == threadInstance.getState()){
          keepRunning = false;
        }
      }
    }catch(InterruptedException iException){
      iException.printStackTrace();
    }

  }
}
//BasicThread.java
package com.javabrahman.corejava.threads;
public class BasicThread implements Runnable {
  @Override
  public void run() {
    Thread thread = Thread.currentThread();
    try{
      //Making the thread sleep for 5 seconds
      System.out.println("Basic thread to sleep for 5 seconds");
      thread.sleep(5000);
      synchronized (thread) {
        thread.wait();
      }
    }catch(InterruptedException iException){
      iException.printStackTrace();
    }
  }
}
 OUTPUT of the above code
BasicThread State: RUNNABLE
Basic thread to sleep for 5 seconds
2 Seconds elapsed - BasicThread State: TIMED_WAITING
4 Seconds elapsed - BasicThread State: TIMED_WAITING
6 Seconds elapsed - BasicThread State: WAITING
8 Seconds elapsed - BasicThread State: TERMINATED
Explanation of the code To better understand how BasicThread.java is moving through different thread states, let us first take a look at a sequence diagram showing the interactions between above two programs -
Sequence Diagram showing Java Thread State Transitions
  • ThreadStates.java is the class with the main() method in above example. It instantiates a BasicThread.java instance, named threadInstance,and then calls start() on threadInstance to start the execution of parallel thread. The state of BasicThread is printed at this point as RUNNABLE.
  • ThreadStates then gets into an infinite while loop with a boolean flag variable named keepRunning. At the beginning of the loop the thread goes to sleep for 2000 milliseconds or 2 seconds. At the same time BasicThread too goes to sleep for 5000 milliseconds.
  • In every iteration of while loop, at a gap of every 2 seconds, BasicThread’s state is printed. During 1st iteration(2 seconds) and 2nd iteration(4 seconds) elapsed times - BasicThread is printed as being in state TIMED_WAITING as it is sleeping for 5 seconds.
  • When 5 seconds elapse BasicThread wakes up, and it immediately asks itself to wait using Thread.wait() method. The state of BasicThread is printed at this point as WAITING.
  • Then, in 3rd iteration i.e. when 6 seconds elapse, ThreadStates invokes notify() on BasicThread which then starts executing.
  • In 4th iteration(8 seconds) ThreadStates checks for BasicThread’s state. The state is now TERMINATED. The flag keepRunning is now set to false. ThreadStates exits the while loop and ends its processing.
Summary In the above tutorial, 2nd in the Java Concurrency Series, we understood the lifecycle of a thread, looked at different thread states, and saw how a thread moves through the different states during its life. In the next tutorial in this series we will take a look at the thread characteristics and how they can used to control the execution of threads as required.