A thread terminates when its run
method stops. Sometimes it may be needed to terminate a task that is being executed, e.g. while shutting down an application with multiple threads. Java provides a mechanism called interruptions for requesting a thread to stop or to do something else. An interruption does not force a thread to react immediately but notifies its about such need.
Interrupt() and isInterrupted()
Invoking the
interrupt()
method on an instance of the Thread
class sets its interrupted flag as true
.Thread thread = ...
thread.interrupt(); // interrupt this thread
The reaction to this event is determined by the interrupted thread itself. One common use case for that is to stop the execution. But, also a thread can simply ignore it.
Depending on the current state of a thread, interruptions are handled differently. Invoking
thread.interrupt()
will cause InterruptedException
if the thread is sleeping or joining other thread. Otherwise, only the interrupted flag will be set to true
.Here is an example of how a thread may handle an interruption:
public class CustomThread extends Thread {
@Override
public void run() {
while (!isInterrupted()) {
try {
doAction();
Thread.sleep(1000); // it may throw InterruptedException
} catch (InterruptedException e) {
System.out.println("sleeping was interrupted");
break; // stop the loop
}
}
System.out.printf("%s finished", getName());
}
private void doAction() {
// something useful
}
}
When this thread is running, an interruption may occur on any statement inside the run method including checking the loop's condition, performing
doAction
and during sleep. If the thread is sleeping, Thread.sleep(1000)
throws an InterruptedException
that is handled. In other cases, the loop is stopped according to the condition on the next iteration.If you prefer implementing
Runnable
rather than extending Thread
directly, you may use the static method Thread.interrupted()
inside the run method. The main difference between this and previous methods is the static method resets the interruption status to false
.An example: counting with interruption
As a complete example, we will consider a task that counts numbers while the thread is not interrupted.
class CountingTask implements Runnable {
@Override
public void run() {
System.out.println("Start counting");
int i = 1; // the first number to print
try {
while (!Thread.interrupted()) {
System.out.println(i);
i++;
Thread.sleep(1000);
}
} catch (InterruptedException e) {
System.out.println("Sleeping was interrupted");
}
System.out.println("Finishing");
}
}
In this implementation, the sleep takes almost all the time and interruption will often occur during sleeping. If the program does not print the string "Sleeping was interrupted", it means, the thread was interrupted during work, not sleep.
In the main method we creating a thread to perform the task, and then interrupts the thread.
public class InterruptionDemo {
public static void main(String[] args) throws InterruptedException {
Thread counter = new Thread(new CountingTask());
counter.start();
Thread.sleep(5000L);
counter.interrupt();
counter.join();
}
}
Note, in the
main
method, both methods sleep
and join
may also throw InteruptedException
upon interrupted. Handling this was omitted only for brevity.The program output:
Start counting
1
2
3
4
Sleeping was interrupted
Finishing