For working professionals
For fresh graduates
More
6. JDK in Java
7. C++ Vs Java
16. Java If-else
18. Loops in Java
20. For Loop in Java
46. Packages in Java
53. Java Collection
56. Generics In Java
57. Java Interfaces
60. Streams in Java
63. Thread in Java
67. Deadlock in Java
74. Applet in Java
75. Java Swing
76. Java Frameworks
78. JUnit Testing
81. Jar file in Java
82. Java Clean Code
86. Java 8 features
87. String in Java
93. HashMap in Java
98. Enum in Java
101. Hashcode in Java
105. Linked List in Java
109. Array Length in Java
111. Split in java
112. Map In Java
115. HashSet in Java
118. DateFormat in Java
121. Java List Size
122. Java APIs
128. Identifiers in Java
130. Set in Java
132. Try Catch in Java
133. Bubble Sort in Java
135. Queue in Java
142. Jagged Array in Java
144. Java String Format
145. Replace in Java
146. charAt() in Java
147. CompareTo in Java
151. parseInt in Java
153. Abstraction in Java
154. String Input in Java
156. instanceof in Java
157. Math Floor in Java
158. Selection Sort Java
159. int to char in Java
164. Deque in Java
172. Trim in Java
173. RxJava
174. Recursion in Java
175. HashSet Java
177. Square Root in Java
190. Javafx
Java supports the powerful multithreading concept, allowing multiple threads to run in parallel. This feature is essential for developing efficient, responsive, and real-time applications. Threads help perform background tasks like downloading files, processing data, or handling user inputs—without blocking the main application.
In this blog, you’ll learn what threads are in Java, how they work, how to create them, manage their lifecycle, and avoid common issues. We’ll also explore practical examples and real-world use cases to strengthen your understanding of multithreading in Java.
To master concepts like these, Software Engineering courses can provide structured learning and hands-on experience.
A thread in Java is a lightweight, independent path of execution within a program. While every Java application runs on at least one thread (the main thread), you can create additional threads to perform tasks concurrently. Java’s java.lang.Thread class and Runnable interface help create and manage threads easily.
Example:
public class MyThread extends Thread {
public void run() {
System.out.println("Thread is running");
}
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start();
}
}
Output:
Thread is running
Explanation: This code creates a new thread using the Thread class. The run() method defines the task, and start() begins execution.
Master in-demand skills with these popular programs.
Multitasking means executing multiple tasks at the same time. In programming, this helps improve performance by utilizing CPU resources more efficiently. Java programming supports multitasking using two approaches: process-based and thread-based multitasking.
Let’s explore each type in detail.
Process-based multitasking involves running multiple programs simultaneously. Each process has its own memory space and resources, isolating it from others. For example, playing music while writing an IDE code involves two processes.
In Java, process-based multitasking is handled by the operating system.
Thread-based multitasking is the ability to run multiple threads within a single process. Since threads share the same memory, they communicate faster but must be managed carefully to avoid conflicts. Java's multithreading feature falls under this category.
It’s used in real-world applications like web servers, gaming, or GUI programs where multiple tasks need to run concurrently.
Must explore: Thread Priority in Java
A Java thread goes through multiple states during its life span. These include New, Active, Blocked/Waiting, Timed Waiting, and Terminated. Understanding Life cycle of Thread helps in debugging and managing thread behavior.
Let’s break down each state.
A thread is in the New state when it is created but not yet started.
Example:
Thread t = new Thread();
Here, t is in the new state.
A thread becomes Active after calling start(). It includes two sub-states:
Example:
Thread t = new Thread(() -> System.out.println("Running"));
t.start();
Output:
Running
A thread enters this state when it’s waiting for a resource or signal to continue execution.
Example:
synchronized(obj) {
obj.wait();
}
Here, the thread waits until it’s notified.
This state occurs when a thread waits for a specified amount of time.
Example:
Thread.sleep(2000);
Explanation: The thread pauses for 2 seconds.
When a thread completes its execution or is forcibly stopped, it enters the Terminated state.
Example:
public void run() {
System.out.println("Done");
}
Once run() finishes, the thread is terminated.
The thread life cycle flows as: New → Runnable → Running → (Waiting/Timed Waiting/Blocked) → Terminated. Java’s Thread class provides methods like start(), sleep(), and join() to manage these transitions.
Understanding this flow is essential for writing efficient and bug-free multithreaded applications.
Java provides two main ways to create a thread:
Let’s understand both methods with syntax and examples.
In this method, you create a new class that extends the built-in Thread class and override its run() method. When you call start(), it internally calls the run() method. This is simple but limits your class from extending any other class due to Java's single inheritance.
Syntax:
class MyThread extends Thread {
public void run() {
System.out.println("Thread running");
}
}
Example:
class MyThread extends Thread {
public void run() {
System.out.println("Thread is running using Thread class.");
}
public static void main(String[] args) {
MyThread t1 = new MyThread();
t1.start(); // Starts the thread
}
}
Output:
Thread is running using Thread class.
Explanation:
Here, the MyThread class extends Thread, and the run() method defines the task. Calling start() internally invokes run() in a new thread.
Here, you define a class that implements the Runnable interface and provide the logic inside the run() method. You then pass this object to a Thread instance and call start(). This approach is more flexible and preferred when your class needs to extend another class.
Syntax:
class MyRunnable implements Runnable {
public void run() {
System.out.println("Runnable running");
}
}
Example:
class MyRunnable implements Runnable {
public void run() {
System.out.println("Thread is running using Runnable interface.");
}
public static void main(String[] args) {
MyRunnable runnable = new MyRunnable();
Thread t1 = new Thread(runnable);
t1.start(); // Starts the thread
}
}
Output:
Thread is running using Runnable interface.
Here, MyRunnable implements Runnable, and its run() method is passed to a Thread object. This approach is preferred when you want your class to extend another class.
After creating a thread, use the start() method to run it. This internally calls the run() method.
Example:
public class Demo {
public static void main(String[] args) {
Thread t = new Thread(() -> System.out.println("Running"));
t.start();
}
}
Output:
Running
Explanation: The lambda expression defines the task, and start() initiates the thread.
When multiple threads access shared resources, concurrency issues like race conditions may occur. These can lead to unpredictable behavior and bugs.
Use synchronization to avoid such problems.
Example:
class Counter {
int count = 0;
synchronized void increment() {
count++;
}
}
Explanation: The synchronized keyword ensures only one thread accesses the method at a time.
Threads are used in many real-world Java applications:
Multithreading enhances performance and ensures responsive software.
Thread in Java make programs more efficient, interactive, and responsive. Understanding thread creation, life cycle, and synchronization is crucial for building real-time and concurrent applications. By following best practices and mastering key concepts, you can handle complex tasks effectively.
Calling start() creates a new thread and executes the run() method on it. Calling run() directly doesn’t start a new thread—it just runs the code in the current thread like a normal method.
No, once a thread has finished execution and reached the terminated state, it cannot be restarted. You must create a new thread object to execute the task again.
Calling start() more than once on the same thread object throws an IllegalThreadStateException. A thread can only be started once. You’ll need to create a new thread instance to start again.
sleep() is a static method of Thread used to pause execution for a specific time. wait() is from Object and is used for thread synchronization—it pauses until another thread calls notify() or notifyAll().
Calling run() directly doesn’t create a new thread; it just executes in the current thread. To achieve true multithreading, the start() method must be used, which internally calls run() in a new thread.
The join() method makes one thread wait for another to complete its execution. It’s useful when the final result depends on the completion of another thread’s task.
Yes, starting from Java 8, you can use lambda expressions with the Runnable interface. Internally, you still need to pass it to a Thread object to execute it.
Thread starvation happens when low-priority threads don’t get CPU time because high-priority threads dominate. It can be avoided using fair thread scheduling with thread pools or proper synchronization techniques.
Daemon threads are background service threads that run until all user threads finish. They’re used for tasks like garbage collection. User threads are primary threads that keep the application running.
Thread priority is a hint to the thread scheduler about the importance of threads, ranging from 1 (MIN) to 10 (MAX). However, it doesn’t guarantee execution order as scheduling is OS-dependent.
Thread pools manage a group of reusable threads, avoiding the overhead of creating and destroying threads repeatedly. They improve performance and are ideal for executing large numbers of short tasks efficiently using the ExecutorService.
Take the Free Quiz on Java
Answer quick questions and assess your Java knowledge
Author|900 articles published
Previous
Next
Talk to our experts. We are available 7 days a week, 9 AM to 12 AM (midnight)
Indian Nationals
1800 210 2020
Foreign Nationals
+918068792934
1.The above statistics depend on various factors and individual results may vary. Past performance is no guarantee of future results.
2.The student assumes full responsibility for all expenses associated with visas, travel, & related costs. upGrad does not provide any a.