Java

Lifecycle and States of a Thread in Java

Java is one of the most popular programming languages for building multi-threaded applications. Understanding the lifecycle and states of a thread in Java is crucial for writing efficient, concurrent programs. Threads allow a program to perform multiple tasks simultaneously, which is especially important for real-world applications like web servers, data processing, and GUI applications.

In this guide, we will explore the thread lifecycle in Java, different thread states, their transitions, practical examples, and best practices for beginners and intermediate learners.

What is a Thread in Java?

A thread is the smallest unit of execution in a Java program. Java supports multithreading, which allows multiple threads to run concurrently. Each thread operates independently but shares the same memory space of the application.

Key benefits of using threads:

  • Improved application performance
  • Better CPU utilization
  • Responsive user interfaces
  • Simultaneous execution of background tasks

Lifecycle of a Thread in Java

Every thread in Java goes through a lifecycle with different states. The Java Thread lifecycle is managed by the Java Virtual Machine (JVM) and consists of the following stages:

  • New (Created)
  • Runnable
  • Running
  • Blocked/Waiting
  • Timed Waiting
  • Terminated (Dead)

1. New (Created) State

When a thread is created using either the Thread class or Runnable interface but not yet started, it is in the new state.

Example:

class MyThread extends Thread { public void run() { System.out.println("Thread is running..."); } } public class ThreadExample { public static void main(String[] args) { MyThread t1 = new MyThread(); // Thread in New state System.out.println("Thread created: " + t1.getName()); } }

Explanation: The thread

t1 is created but not yet started. Calling t1.start() will move the thread from New to Runnable state.

2. Runnable State

A thread enters the Runnable state when

start() is called. It is ready to run, but it waits for CPU scheduling.

Example:

MyThread t1 = new MyThread(); t1.start(); // Thread now in Runnable state

Explanation: Runnable does not mean the thread is currently running; it is eligible for execution. The JVM thread scheduler decides when the thread will move to the Running state.

3. Running State

A thread enters the Running state when the JVM scheduler picks it from the Runnable pool. Only one thread per core can run at a time, and the thread actively executes its task in this state.

Example:

class MyThread extends Thread { public void run() { System.out.println(Thread.currentThread().getName() + " is running"); } } public class ThreadExample { public static void main(String[] args) { MyThread t1 = new MyThread(); t1.start(); // Runnable -> Running } }

Explanation:

  • When start() is called, the thread moves from Runnable to Running when the JVM thread scheduler picks it for execution.
  • Only one thread executes at a time on a single CPU core. Other threads wait their turn via time-slicing or priority scheduling.
  • The run() method contains the code that will execute while the thread is in the Running state.

3. Running State

A thread enters the Running state when the JVM scheduler picks it from the Runnable pool. Only one thread per core can run at a time, and the thread actively executes its task in this state.

Example:

class MyThread extends Thread { public void run() { System.out.println(Thread.currentThread().getName() + " is running"); } } public class ThreadExample { public static void main(String[] args) { MyThread t1 = new MyThread(); t1.start(); // Runnable -> Running } }

Explanation:

  • When
    start() is called, the thread moves from Runnable to Running when the JVM thread scheduler picks it for execution.
  • Only one thread executes at a time on a single CPU core. Other threads wait their turn via time-slicing or priority scheduling.
  • The
    run() method contains the code that will execute while the thread is in the Running state.

3. Running State

A thread enters the Running state when the JVM scheduler picks it from the Runnable pool. Only one thread per core can run at a time.

Example:

class MyThread extends Thread { public void run() { System.out.println(Thread.currentThread().getName() + " is running"); } } public class ThreadExample { public static void main(String[] args) { MyThread t1 = new MyThread(); t1.start(); // Runnable -> Running } }

4. Blocked/Waiting State

A thread enters the Blocked state when it is waiting to acquire a lock on an object. Similarly, the Waiting state occurs when a thread waits indefinitely until another thread signals it.

Example:

class SharedResource { synchronized void display() { System.out.println(Thread.currentThread().getName() + " is accessing resource"); try { Thread.sleep(2000); } catch (InterruptedException e) { } } } public class ThreadExample { public static void main(String[] args) { SharedResource resource = new SharedResource(); Thread t1 = new Thread(() -> resource.display()); Thread t2 = new Thread(() -> resource.display()); t1.start(); t2.start(); // t2 may enter Blocked state } }

5. Timed Waiting State

A thread enters Timed Waiting when it waits for a specific amount of time using methods like sleep(), join(timeout), or wait(timeout).

Example:

Thread t1 = new Thread(() -> { try { Thread.sleep(3000); // Timed Waiting System.out.println("Thread finished sleeping"); } catch (InterruptedException e) { e.printStackTrace(); } }); t1.start();

6. Terminated (Dead) State

A thread enters the Terminated state once it completes execution or is stopped. Once dead, a thread cannot be restarted.

Example:

Thread t1 = new Thread(() -> System.out.println("Thread completed")); t1.start(); System.out.println("Is thread alive? " + t1.isAlive()); // false if terminated

Thread States Summary Table

Thread State Description Example Method
New Thread created but not started new Thread()
Runnable Thread ready to run, waiting for CPU start()
Running Thread executing its task run()
Blocked/Waiting Thread waiting for lock or signal synchronized / wait()
Timed Waiting Thread waiting for a specified time sleep() / join(timeout)
Terminated (Dead) Thread finished execution N/A

Real-World Examples of Threads in Java

  • Web Servers: Multiple threads handle concurrent HTTP requests.
  • GUI Applications: Background threads prevent UI freezing during tasks.
  • Data Processing: Threads process large datasets in parallel.
  • Network Applications: Threads manage simultaneous client connections.

Practical Use Case: Downloading Multiple Files

class FileDownloader extends Thread { String fileName; FileDownloader(String fileName) { this.fileName = fileName; } public void run() { System.out.println("Downloading: " + fileName); try { Thread.sleep(2000); } catch (InterruptedException e) { } System.out.println("Downloaded: " + fileName); } } public class MultiDownload { public static void main(String[] args) { FileDownloader f1 = new FileDownloader("file1.pdf"); FileDownloader f2 = new FileDownloader("file2.pdf"); f1.start(); f2.start(); } }

Best Practices for Java Threads

  • Avoid blocking the main thread for long tasks.
  • Use synchronization to prevent race conditions.
  • Prefer ExecutorService over manually creating threads.
  • Always handle InterruptedException properly.
  • Monitor thread states using isAlive() and getState().

FAQs About Java Thread Lifecycle

1. What is the difference between Runnable and Running states?

Runnable: Thread is ready to run but waiting for CPU scheduling.
Running: Thread is actively executing its task.

2. Can a thread be restarted once it is terminated?

No, a terminated thread cannot be restarted. You need to create a new thread object.

3. How can I check the current state of a thread?

Thread t = new Thread(); System.out.println(t.getState());

4. What is the difference between Blocked and Timed Waiting?

  • Blocked: Waiting indefinitely for a resource lock.
  • Timed Waiting: Waiting for a specific time period using sleep() or join(timeout).

5. Why is understanding thread lifecycle important?

Knowing the lifecycle helps in:

  • Efficient resource management
  • Avoiding deadlocks and race conditions
  • Writing responsive and concurrent applications

Understanding the lifecycle and states of a thread in Java is fundamental for building efficient and responsive applications. By mastering thread states like New, Runnable, Running, Waiting, Timed Waiting, and Terminated, developers can manage concurrency, improve performance, and prevent common pitfalls such as deadlocks or race conditions. Practical examples, from GUI apps to file downloads, demonstrate how threads can be applied in real-world scenarios. Following best practices ensures threads operate safely and efficiently in your Java applications.

line

Copyrights © 2024 letsupdateskills All rights reserved