In Java Programming, threads allow the expression and execution of multiple operations and activities within a single application. It facilitates the synchronized running of threads in Java and allows for proper management of the threads run in the Java virtual machine; it is important to understand their life cycle and the various states these threads go through. The thread life cycle in Java means the various states that a thread might pass through as it runs. At any given time in its life cycle, a thread can be in any state and is bound to exhibit some other behaviour concerning its state. This article will detail the thread life cycle and its states in Java.
What are Threads in Java?
Before we go through the thread life cycle in Java, let us briefly understand threads in Java. Java thread is a low-level process that helps run multiple tasks in parallel in a single application. It enhances the system’s performance by allowing an application to execute two or more actions simultaneously. There is also a slight difference in the states of thread, which includes the ready, running, waiting, and dead state when in their life cycle. They are also referred to as lightweight processes because they have other threads in the same process that address space-share resources.
The Java programming language has an important element called threads for parallelism and strategies such as performance and responsiveness. In short, Threads are one of the most essential concepts of Java’s multi-threaded program. Java is a dominant language in data science and business analytics. Hence, learning a thread’s life cycle and state in Java is critical to professional engineering practice.
Get curriculum highlights, career paths, industry insights and accelerate your technology journey.
Download brochure
Creating a Thread in Java
A thread in Java can be created in two ways.
Extending java.lang.Thread class: We can create the thread class by creating the class and an instance of that class. The run() method includes the functionality that is supported to be implemented by the Thread.
Below is an example of creating a thread by extending the java.lang thread class.
public class MyThread extends Thread{
public void run(){
System.out.println("Thread is running");
}
public static void main(String args[]){
MyThread ob = new MyThread() ;
ob.start() ;
}
}
Output
Thread is running
Implementing Runnable Interface: Creating a thread between the two is easy. In this case, a class is created to implement the runnable interface and the run() method.
public class MyThread implements Runnable{
public void run(){
System.out.println("Thread is running");
}
public static void main(String args[]){
Thread t = new Thread (new MyThread()) ;
t.start() ;
}
}
Output
Thread is running
Java Thread Priorities
The priority scale runs from 1 to 10, and any thread generated in the JVM is assigned a priority based on its number of services.
1 is known as the lowest priority.
5 is known as the standard priority
10 represents the highest level of priority.
Thread.MIN_PRIORITY;
THREAD.NORM_PRIORITY
Thread.MAX_PRIORITY
It is the understanding of the Thread Priority.
class ThreadPriority extends Thread{
public void run(){
System.out.println("Running Thread priority is "+ Thread.currentThread().getPriority());
}
public static void main(String args[]){
ThreadPriority ob = new ThreadPriority();
ThreadPriority ob2 = new ThreadPriority() ;
ob.setPriority(Thread.MIN_PRIORITY);
ob2.setPriority(Thread.MAX_PRIORITY);
ob.start();
ob2.start() ;
}
}
Output
Running Thread priority is 1
Running Thread priority is 10
Most Commonly Used Constructors in Thread Class
The thread class includes constructors and methods for creating and operating on threads. The thread extends the Object and implements the Runnable interface.
Thread(): The default Thread() constructor creates a new class.
public class ThreadExample extends Thread{
public static void main(String[] args){
Thread ob = new Thread() ;
ob.start();
System.out.println("Thread has been created with name"+ob.getName());
}
}
Output
Thread has been created with nameThread-0
Thread (Runnable r)
It is the constructor type. That reference is passed, and a new Thread object is created.
class Testing implements Runnable{
public void run(){
System.out.println("Do Something");
}
}
public class ThreadExample extends Thread{
public static void main(String[] args){
Thread ob = new Thread(new Testing()) ;
ob.start();
System.out.println("Thread has been crated with name"+ob.getName());
}
}
Output
Thread has been created with nameThread-0
Do Something
Multithreading in Java
In Java, multithreading means running it in parallel with two or more threads simultaneously to utilize the maximum CPU. Therefore, it is sometimes called Java Concurrency. The others run in parallel with each thread. Since different memory spaces aren’t assigned to several threads, they apply to memory. In addition, it doesn’t take much time to switch between threads.
Java multithreading simplifies and shortens program structure. Using generalized threads in high-server media applications allows one to vary or improve the configuration of these complicated structures without tweaking every scene voxel.
Here is an example of Multithreading in the Java language
public class Example1 implements Runnable{
public static void main(String[]args){
Thread ob = new Thread("Demo1") ;
Thread ob2 = new Thread("Demo2") ;
ob.start() ;
ob2.start() ;
System.out.println("Thread names are following") ;
System.out.println(ob.getName());
System.out.println(ob.getName());
}
}
Output
Thread names are the following.
Demo1
Demo1
Importance of Understanding the Life Cycle of Thread in Java and Its States
The thread life cycle in Java is an important concept in multithreaded applications. Let’s see the importance of understanding the life cycle of a thread in Java:
Understanding Java’s life cycle and states is essential for identifying potential issues that can arise when creating or manipulating threads.
It allows developers to utilize resources more effectively and prevent errors related to multiple threads accessing shared data simultaneously.
Knowing the thread states in Java helps predict a program’s behavior and debug any issues that may arise.
It also guides the developer on properly suspending, resuming, and stopping a thread as required for a specific.
The Life Cycle of Thread in Java – Thread State
In Java, the life cycle of Thread goes through various states. These states represent different stages of execution. Here are examples of each stage of the life cycle of Thread in Java with real-life use cases:
1. New (born) state
Example: Creating a new thread using the Thread class constructor.
Use case: Creating a new thread to perform a background task while the main Thread continues with other operations
2. Runnable state
Example: After calling the start() method on a thread, it enters the runnable state.
Use case: Multiple threads competing for CPU time to perform their tasks concurrently.
3. Running state
Example: When a thread executes its code inside the run() method.
Use case: A thread executing a complex computation or performing a time-consuming task.
4. Blocked state:
An example is an attempt by some thread to access a synchronized block or method while another thread has control of the lock to the block or method.
Coordination of more than one thread implies that several threads can only perform write or read operations on a resource that is the same, for instance, a database or a file by using that single thread.
5. Waiting state:
Example: Inside a synchronized block, a thread can use the wait method, wait for another thread to call the notify method, or notifyAll method to awake the wait method.
Use case: It implements the producer-consumer pattern, where a thread waits for a specific to be met before executing it.
6. Timed waiting state:
Example: Using methods like sleep(milliseconds) or join(milliseconds) causes a thread to enter the timed waiting state for the specified duration.
Use case: Adding delays between consecutive actions or waiting for the completion of other threads before proceeding.
7. Terminated state:
Example: When the run() method finishes its execution or when the stop() method is called on the Thread.
Use case: Completing a task or explicitly stopping a thread’s execution.
These examples demonstrate how threads can handle various scenarios in Java applications, allowing for concurrent and parallel execution of tasks. Understanding the different thread states helps in designing efficient and responsive multithreaded applications. Moreover, access modifiers in Java are also important to understand. Since these are used in multithreading programming, knowledge of them is important.
Transitions Between Thread States
Threads in a multithreaded environment can transition between different thread states in Java as they execute. The Java Thread class defines these states and represents different stages in the lifecycle of a thread. The possible states include:
New: When a thread has just been created, it is in the “New” state. At this point, the Thread is not yet scheduled for execution and has not started running.
Runnable: A thread becomes “Runnable” when the start() method has been called on it. In this state, the Thread is in the ready queue for the OS scheduler to execute the Thread’s code.
Blocked/Waiting: It should be noted that a thread can either be in the “Blocked” or “Waiting” mode depending on some conditions. For example, if the thread is waiting for a lock of another thread, it must go into the “Blocked” state. Likewise, if a thread expects a particular condition to occur, then the thread becomes “Waiting.” The Thread is dormant in these states and cannot be placed on the scheduling queue.
Timed Waiting: Threads can also enter the “Timed Waiting” state, similar to the “Waiting” state but with a time constraint. For instance, a thread can enter the “Timed Waiting” state when it calls methods like Thread.sleep() or Object.wait() with a specific timeout value. The Thread remains in this state until the timeout expires or until it receives a notification from another thread.
Terminated: The final state in the thread lifecycle is the “Terminated” state. A thread enters this state when it completes its execution or when an unhandled exception occurs within the Thread. Once a thread is terminated, it cannot transition to any other state.
class MyThread implements Runnable {
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + " is RUNNING");
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName() + " is in WAITING/SLEEPING");
synchronized (this) {
wait(1000);
System.out.println(Thread.currentThread().getName() + " is in TIMED_WAITING");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " is TERMINATED");
}
}
public class ThreadStatesDemo {
public static void main(String[] args) {
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread, "MyThread");
System.out.println(thread.getName() + " is in NEW state");
thread.start();
System.out.println(thread.getName() + " is RUNNABLE");
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Output
MyThread is in NEW state
MyThread is RUNNABLE
MyThread is RUNNING
MyThread is in WAITING/SLEEPING
MyThread is in TIMED_WAITING
MyThread is TERMINATED
Handling Thread Exceptions and Termination Threads
There are several ways to handle exceptions in the life cycle of a Java thread.
The most common way is wrapping the code in a try-catch block.
Moreover, when a thread is no longer needed, it should be terminated for the application to avoid memory leaks and other issues. To do this, invoke the Thread’s interrupt() or stop() methods. The former method sends an interruption signal to the Thread, while the latter stops it immediately and can cause instability in some cases.
When managing threads, certain best practices and tips can keep the discussion organized and productive.
Keep conversations on-topic: To ensure a thread is productive, make sure everyone stays on-topic and focused on the subject at hand.
Monitor for trolling: Be alert for blogging trolls who are out to post messages that are designed to disrupt conversation. In cases where one becomes abrasive or arrogant, do not hesitate to question him or her and, if possible, block the person from your website.
Stay organized: Monitor the conversation using threads and other organizational tools. If necessary, assign a moderator to ensure everything stays on track and everyone is heard.
Respond promptly: Respond promptly when someone asks a question or raises an issue. This will help keep the discussion productive and ensure everyone’s questions are answered promptly.
Considerations for Designing Multithreaded Applications
Designing multithreaded applications can be a complex process with many factors to consider, such as:
Synchronization
Thread synchronization refers to the arrangements made when two or more threads can access the same data consistently. There are four methods of synchronizing threads: locks, semaphores, monitors, and atomic operations.
Memory Management
Each Thread may require its own memory space, and multiple threads might need to access the same data from varied locations in memory. Careful memory management is required to ensure all threads can access the correct data at the right time.
Multiple Thread Source Allocation
Threads may also need to share resources such as processors, files or network connections. Resource allocation must be carefully managed to ensure that all threads get the resources they need when needed.
Performance
Multithreading in Java can benefit performance, as multiple threads work concurrently on different tasks. Careful threading design is required to ensure the application effectively uses system resources and achieves the desired problems.
How to Handle Thread Deadlock
The term deadlock is specific to a scenario when multiple threads can wait for each other indefinitely and get stuck until one of them releases. Deadlock occurs when several threads require the same locks but receive them in different orders. In a Java multithreaded program, however, the synchronized keyword causes the executing thread to block until the lock it waits for (on the specified object) becomes available. Always obtain several locks in the same order from many threads to avoid a deadlock. An example of code which can cause deadlock is as follows:
class Example{
private final String name ;
public Example(String name) {
this.name = name ;
}
public String getName() {
return this.name ;
}
public synchronized void call(Example caller){
System.out.println(this.getName()+"has asked to call"+caller.getName());
try{
}catch(Exception e){
e.printStackTrace();
}
caller.callMe(this) ;
}
public synchronized void callMe(Example caller){
System.out.println(this.getName()+"has called me"+caller.getName()) ;
}
public static void main(String args[]){
Example ob = new Example("caller 1") ;
Example ob2 = new Example("caller2") ;
new Thread(new Runnable(){
public void run(){
ob.call(ob) ;
}
}).start();
new Thread(new Runnable(){
public void run(){
ob2.call(ob2);
}
}).start();
}
}
Output
Pet@722c41f4
Pet@722c41f4
Conclusion
Understanding the states and life cycle of threads in Java is essential for creating multithreaded applications. Knowing how to create a thread, pause, resume, or terminate it can help you develop efficient and reliable programs. You can develop your multithreaded applications using Java with a fundamental understanding of these concepts. To further enhance your Java skills and gain a deeper understanding of threading and full stack development, consider the Certificate Program in Full Stack Development with Specialization for Web and Mobile powered by Hero Vired.
FAQs
What precisely is the life cycle of a thread in Java?
The life cycle of a Thread in Java refers to the various stages it goes through during execution. Possible states include New, Runnable, Running, Blocked/Waiting, Timed, and Terminated.
What is multithreading of thread life cycle?
Multithreading in Java is the process of executing multiple threads concurrently within an application. During their lifecycle, threads can be in different states, such as Ready, Running, Blocked/Waiting, or Terminated. Understanding thread states and their interactions is essential for designing efficient multithreaded applications.
What are life cycle methods in Java?
Life cycle methods in Java control a thread's life cycle. These include start(), join(), interrupt() and stop(). Understanding how these methods work to manage threads in your application properly is important.
What are the multiple stages of the life cycle of threads in Java?
The life cycle stages of Java threads are New, Runnable, Running, Blocked/Waiting, Timed Waiting, and Terminated. Each state has its characteristics and behaviour. Understanding these states is important for successful multithreading programming in Java.
Hero Vired is a leading LearnTech company dedicated to offering cutting-edge programs in collaboration with top-tier global institutions. As part of the esteemed Hero Group, we are committed to revolutionizing the skill development landscape in India. Our programs, delivered by industry experts, are designed to empower professionals and students with the skills they need to thrive in today’s competitive job market.