In this section, we will explore the lifecycle of a thread in Java. Understanding the thread lifecycle is crucial for managing threads effectively in a multithreaded environment. The lifecycle of a thread in Java can be broken down into several states:

  1. New
  2. Runnable
  3. Blocked
  4. Waiting
  5. Timed Waiting
  6. Terminated

Let's delve into each of these states in detail.

  1. New

A thread is in the "New" state when it is created but not yet started. This is the initial state of a thread.

Thread thread = new Thread(() -> {
    System.out.println("Thread is running");
});

In the above code, the thread is created but not started, so it is in the "New" state.

  1. Runnable

A thread moves to the "Runnable" state when the start() method is called. In this state, the thread is ready to run and is waiting for the CPU to allocate time for execution.

thread.start();

Once the start() method is called, the thread transitions from the "New" state to the "Runnable" state.

  1. Blocked

A thread enters the "Blocked" state when it is waiting to acquire a monitor lock to enter or re-enter a synchronized block/method.

public synchronized void synchronizedMethod() {
    // critical section
}

If a thread tries to enter a synchronized method and the lock is already held by another thread, it will be blocked until the lock is released.

  1. Waiting

A thread is in the "Waiting" state when it is waiting indefinitely for another thread to perform a particular action. This can happen in several scenarios, such as when a thread calls Object.wait().

synchronized (lock) {
    lock.wait();
}

In the above code, the thread will wait indefinitely until another thread calls lock.notify() or lock.notifyAll().

  1. Timed Waiting

A thread is in the "Timed Waiting" state when it is waiting for another thread to perform an action for a specified waiting time. This can happen when a thread calls methods like Thread.sleep(long millis), Object.wait(long timeout), or Thread.join(long millis).

Thread.sleep(1000); // The thread will be in Timed Waiting state for 1 second

In the above code, the thread will be in the "Timed Waiting" state for 1 second.

  1. Terminated

A thread is in the "Terminated" state when it has completed its execution. This can happen either because the thread has finished executing its run() method or because it was terminated by an exception.

public void run() {
    System.out.println("Thread is running");
    // Thread execution completes here
}

Once the run() method completes, the thread transitions to the "Terminated" state.

Thread Lifecycle Diagram

Here is a visual representation of the thread lifecycle:

New -> Runnable -> Running -> (Blocked/Waiting/Timed Waiting) -> Runnable -> Terminated

Practical Example

Let's see a practical example that demonstrates the different states of a thread.

public class ThreadLifecycleDemo {

    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                System.out.println("Thread is in Runnable state");
                Thread.sleep(1000); // Timed Waiting state
                synchronized (ThreadLifecycleDemo.class) {
                    System.out.println("Thread is in Blocked state");
                    ThreadLifecycleDemo.class.wait(); // Waiting state
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread is in Terminated state");
        });

        System.out.println("Thread is in New state");
        thread.start();
    }
}

In this example:

  • The thread starts in the "New" state.
  • When start() is called, it moves to the "Runnable" state.
  • It then enters the "Timed Waiting" state when Thread.sleep(1000) is called.
  • After waking up, it tries to enter a synchronized block, potentially moving to the "Blocked" state.
  • It then calls wait(), moving to the "Waiting" state.
  • Finally, it completes execution and moves to the "Terminated" state.

Exercises

Exercise 1: Thread States

Create a Java program that demonstrates the transition of a thread through all the states: New, Runnable, Blocked, Waiting, Timed Waiting, and Terminated.

Solution:

public class ThreadStateDemo {

    public static void main(String[] args) {
        Object lock = new Object();

        Thread thread = new Thread(() -> {
            try {
                System.out.println("Thread is in Runnable state");
                Thread.sleep(500); // Timed Waiting state
                synchronized (lock) {
                    System.out.println("Thread is in Blocked state");
                    lock.wait(); // Waiting state
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("Thread is in Terminated state");
        });

        System.out.println("Thread is in New state");
        thread.start();

        try {
            Thread.sleep(100); // Ensure the thread enters Timed Waiting state
            synchronized (lock) {
                lock.notify(); // Move thread from Waiting to Runnable state
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

Exercise 2: Thread Lifecycle Monitoring

Write a Java program that monitors and prints the state of a thread at regular intervals until it terminates.

Solution:

public class ThreadLifecycleMonitor {

    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        thread.start();

        while (thread.getState() != Thread.State.TERMINATED) {
            System.out.println("Thread state: " + thread.getState());
            try {
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("Thread state: " + thread.getState());
    }
}

Conclusion

Understanding the thread lifecycle is essential for effective multithreading in Java. By knowing the different states a thread can be in and how to manage transitions between these states, you can write more efficient and robust multithreaded applications. In the next section, we will explore synchronization mechanisms to manage thread interactions safely.

Java Programming Course

Module 1: Introduction to Java

Module 2: Control Flow

Module 3: Object-Oriented Programming

Module 4: Advanced Object-Oriented Programming

Module 5: Data Structures and Collections

Module 6: Exception Handling

Module 7: File I/O

Module 8: Multithreading and Concurrency

Module 9: Networking

Module 10: Advanced Topics

Module 11: Java Frameworks and Libraries

Module 12: Building Real-World Applications

© Copyright 2024. All rights reserved