JavaMultithreading

Interruptions

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
How did you like the theory?
Report a typo