InterruptedException

April 2019

Back home

In Java, lots of standard library methods throw InterruptedException. How should programs respond to this exception?

This article addresses InterruptedException, an important checked exception thrown by many standard library calls including Thread.join() and Thread.sleep(). The documentation does not describe why this exception exists or what programs should do with it, leading programmers to write code like this:

public void sleepForOneSecond() {
    // WRONG! Do not do this!
    try {
        Thread.sleep(1000);
    } catch (InterruptedException ignored) {
    }
}

Instead, programmers should understand InterruptedException and properly handle it.

What is InterruptedException?

Java is a threaded programming language. Usually threads communicate with each other using locks and shared memory. However, Java offers an additional way for threads to communicate called "interruption". You can interrupt a thread by calling its interrupt() method. (Do not confuse interruption with the interrupt signal for cross-process communication. The two share a tenuous conceptual relationship, but their implementations have nothing to do with each other.)

InterruptedException is thrown when a thread is interrupted during a long-running method. The documentation for interrupt() lists the most important such methods in the standard library. If a thread is interrupted at any other time, no InterruptedException will be thrown. Instead, the thread's "interrupted status" is set to true. Threads can read their own interrupted status using Thread.currentThread().isInterrupted() and reset their interrupted status to false using the poorly-named Thread.interrupted().

How should programs correctly handle InterruptedException?

Java does not prescribe a behavior for interruption: it is a primitive that you may use to build programs. To correctly use it, every thread in your program should have a clear interruption policy and should and adhere to that policy. Here are some useful potential policies:

Note that the wrong source code above using Thread.sleep() does not correctly implement the "ignore interrupts" policy! An interrupt can cause it to return early, making its behavior "sleep for one second or until the first interruption, which ever happens first". Even worse, it provides no mechanism for callers who may wish to handle interrupts to detect that one happened.

If you are interrupting a method that might be called from different threads with different interruption policies, you might

Recipes

Sleep without aborting early due to interruption:

public static void sleepForOneSecondIgnoringInterruptions() {
    final long millisToSleep = 1000;

    final long NANOS_PER_MILLI = 1000 * 1000;
    final long start = System.nanoTime();
    long millisSlept;
    boolean wasInterrupted = false;
    while ((millisSlept = (System.nanoTime() - start) / NANOS_PER_MILLI) < millisToSleep) {
        try {
            Thread.sleep(millisToSleep - millisSlept);
        } catch (InterruptedException interruption) {
            wasInterrupted = true;
        }
    }

    // Preserve the interruption status so that other parts of the program can
    // respond to the interruption however they see fit.
    if (wasInterrupted) {
        Thread.currentThread().interrupt();
    }
}

"Yield" the current thread (to let others run) by sleeping for a very short time:

public static void yield() {
    try {
        Thread.sleep(1);
    } catch (InterruptedException interruption) {
        // Preserve the interruption status so that other parts of the program
        // can respond to the interruption however they see fit.
        Thread.currentThread().interrupt();
    }
}

Back home