In Java, interrupting a thread is a way of signaling a thread to stop its current execution.
While threads do not stop immediately when interrupted, they can respond to the interruption signal and stop gracefully by checking their interrupt status or handling the InterruptedException.
In this tutorial, we will cover:
- What is Thread Interruption in Java?
- Using interrupt() to Signal a Thread
- Checking the Interrupt Status
- Handling InterruptedException
- Best Practices for Handling Thread Interruption
- Examples and Use Cases
Let’s explore each concept with examples.
1. What is Thread Interruption in Java?
In Java, thread interruption is a mechanism to signal a thread that it should stop its current work. However, thread interruption does not stop the thread immediately.
Instead, it is up to the thread to regularly check its interrupt status or handle an InterruptedException to stop gracefully.
Java threads have a flag called the interrupt flag, which is set when interrupt() is called on the thread.
The thread can check this flag by using methods like Thread.interrupted() or isInterrupted() to decide if it should stop or continue its execution.
2. Using interrupt() to Signal a Thread
The interrupt() method is used to signal a thread that it has been interrupted. This method does not forcefully terminate the thread but sets the interrupt flag to true, which can be checked or handled within the thread.
Example 1: Signaling a Thread Using interrupt()
class MyThread extends Thread { public void run() { System.out.println("Thread is running..."); for (int i = 1; i <= 10; i++) { System.out.println("Working on task " + i); // Simulate some work with sleep try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("Thread was interrupted during sleep."); return; // Stop execution when interrupted } } System.out.println("Thread completed."); } } public class InterruptExample { public static void main(String[] args) { MyThread thread = new MyThread(); thread.start(); try { // Give the thread some time to run Thread.sleep(3000); // Main thread sleeps for 3 seconds } catch (InterruptedException e) { e.printStackTrace(); } // Interrupt the thread after 3 seconds thread.interrupt(); System.out.println("Thread interrupt signal sent."); } }
Output:
Thread is running... Working on task 1 Working on task 2 Working on task 3 Thread was interrupted during sleep. Thread interrupt signal sent.
Explanation:
- The interrupt() method sends a signal to the thread. The thread does not stop immediately but can check the interrupt status and handle it.
- In the example, the thread is interrupted during its sleep(), and the InterruptedException is caught. The thread then terminates gracefully.
3. Checking the Interrupt Status
You can check a thread's interrupt status using either Thread.interrupted() or isInterrupted().
- Thread.interrupted(): Checks if the current thread has been interrupted and clears the interrupt flag after checking.
- isInterrupted(): Checks if the thread has been interrupted without clearing the flag.
Example 2: Checking the Interrupt Status Using isInterrupted()
class MyTask implements Runnable { public void run() { System.out.println("Thread is running..."); for (int i = 1; i <= 5; i++) { System.out.println("Task " + i); // Check if the thread has been interrupted if (Thread.currentThread().isInterrupted()) { System.out.println("Thread was interrupted. Exiting..."); break; } // Simulate some work with sleep try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("Thread was interrupted during sleep."); return; } } System.out.println("Thread completed."); } } public class InterruptCheckExample { public static void main(String[] args) { Thread thread = new Thread(new MyTask()); thread.start(); try { Thread.sleep(2000); // Main thread sleeps for 2 seconds } catch (InterruptedException e) { e.printStackTrace(); } // Interrupt the thread after 2 seconds thread.interrupt(); } }
Output:
Thread is running... Task 1 Task 2 Thread was interrupted. Exiting... Thread was interrupted during sleep.
Explanation:
- The isInterrupted() method is used to check if the thread has been interrupted.
- When the interrupt flag is set, the thread checks this status and exits the loop early.
4. Handling InterruptedException
When a thread is interrupted during a blocking operation like Thread.sleep(), wait(), or join(), it throws an InterruptedException. This exception must be handled inside the thread to ensure the thread responds to interruptions.
Example 3: Handling InterruptedException in Thread
class BlockingTask implements Runnable { public void run() { System.out.println("Thread is performing a blocking operation..."); try { // Simulating a long operation with sleep Thread.sleep(5000); } catch (InterruptedException e) { System.out.println("Thread was interrupted during a blocking operation."); return; // Stop execution when interrupted } System.out.println("Thread finished blocking operation."); } } public class InterruptBlockingExample { public static void main(String[] args) { Thread thread = new Thread(new BlockingTask()); thread.start(); try { Thread.sleep(2000); // Main thread sleeps for 2 seconds } catch (InterruptedException e) { e.printStackTrace(); } // Interrupt the thread while it's performing a blocking operation thread.interrupt(); System.out.println("Interrupt signal sent to the thread."); } }
Output:
Thread is performing a blocking operation... Interrupt signal sent to the thread. Thread was interrupted during a blocking operation.
Explanation:
- The thread is interrupted while it is sleeping (Thread.sleep()), and the InterruptedException is caught. The thread then stops its execution.
5. Best Practices for Handling Thread Interruption
- Check for Interruption Regularly: In long-running tasks or loops, make sure to check the interrupt status regularly using isInterrupted() or Thread.interrupted() to handle interruptions gracefully.
if (Thread.currentThread().isInterrupted()) { // Handle the interruption, e.g., clean up resources or stop the task break; }
- Respond to InterruptedException: When a thread is interrupted during a blocking operation, such as sleep() or wait(), it should handle the InterruptedException by cleaning up and stopping the task.
try { Thread.sleep(1000); } catch (InterruptedException e) { // Handle the exception and stop the thread Thread.currentThread().interrupt(); // Preserve the interrupt status return; }
- Preserve the Interrupt Status: If you catch an InterruptedException, it's a good practice to call Thread.currentThread().interrupt() to restore the interrupt flag if you intend to propagate the interruption.
6. Examples and Use Cases
Example 4: Gracefully Stopping a Long-Running Task
Let’s say you have a long-running task that should stop when an interrupt signal is received. You can check for interruptions in each iteration of the task.
class LongRunningTask implements Runnable { public void run() { for (int i = 1; i <= 10; i++) { System.out.println("Processing task " + i); // Check for interrupt signal if (Thread.currentThread().isInterrupted()) { System.out.println("Thread was interrupted. Stopping task..."); break; } // Simulate a time-consuming operation try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("Thread was interrupted during sleep. Exiting..."); return; } } System.out.println("Task completed."); } } public class LongRunningTaskExample { public static void main(String[] args) { Thread thread = new Thread(new LongRunningTask()); thread.start(); try { Thread.sleep(4000); // Main thread sleeps for 4 seconds } catch (InterruptedException e) { e.printStackTrace(); } // Interrupt the thread thread.interrupt(); } }
Output:
Processing task 1 Processing task 2 Processing task 3 Processing task 4 Thread was interrupted. Stopping task...
Explanation:
- The thread processes tasks in a loop, checking the interrupt flag during each iteration.
- When the interrupt signal is sent, the thread stops gracefully before completing all tasks.
Summary of Key Concepts for Thread Interruption
Concept | Description |
---|---|
interrupt() | Signals a thread that it has been interrupted by setting the interrupt flag to true. |
isInterrupted() | Checks if the current thread has been interrupted without clearing the interrupt flag. |
Thread.interrupted() | Checks if the current thread has been interrupted and clears the interrupt flag. |
InterruptedException | Thrown when a thread is interrupted during a blocking operation (like sleep(), wait(), or join()). |
Best Practice | Regularly check for interruptions and handle InterruptedException properly by cleaning up and stopping the task. |
Restoring Interrupt Status | If you catch InterruptedException, call Thread.currentThread().interrupt() to restore the interrupt status. |
Conclusion
In this tutorial, we explored how to interrupt threads in Java using the interrupt() method and handle thread interruptions gracefully.
We covered:
- The use of the interrupt() method to signal threads.
- How to check the interrupt status using isInterrupted() and Thread.interrupted().
- Handling InterruptedException when a thread is performing a blocking operation.
- Best practices for handling thread interruptions in long-running tasks.