javamultithreadingconcurrencyinterrupted-exceptioninterruption

Thread is interrupted by calling interrupt(), but Thread.isInterrupted() returns false


I am testing InterruptedException with the following test code:

Runnable runMe = new Runnable() {
    @Override
    public void run() {
        for(int i=0; i<6; i++) {
            System.out.println("i = "+i);
            if(i==3) {
                System.out.println("i==3, Thread = " 
                +Thread.currentThread().getId());
                //I invoke interrupt() on the working thread.
                Thread.currentThread().interrupt();
                try {
                    Thread.currentThread().join();
                } catch (InterruptedException e) {
                    //I caught InterruptedException
                    System.out.println(Thread.currentThread().getId() 
                    + " is interrupted!");
                    Thread.currentThread().interrupt();
                }
            }
        }
    }   
};          
Thread workingThread = new Thread(runMe);
workingThread.start();
try {
    workingThread.join();
} catch (InterruptedException e) {
    //Swallow
}
//the following log shows me workingThread.isInterrupted() is false, why?
System.out.println("workingThread(" 
+ workingThread.getId()+") interrupted ? " 
+ workingThread.isInterrupted());

In run() , I interrupt() current working thread, and caught a InterruptedException.

In main thread, my last line of code is a System.out.println(...) which prints out the interrupt status of working thread. Since I have caught InterruptedException in run(), I though I should get the message that workingThread.isInterrupted() is true, but I got false, why?


Solution

  • Oracle's Java concurrency tutorial says (my emphasis added):

    The Interrupt Status Flag

    The interrupt mechanism is implemented using an internal flag known as the interrupt status. Invoking Thread.interrupt sets this flag. When a thread checks for an interrupt by invoking the static method Thread.interrupted, interrupt status is cleared. The non-static isInterrupted method, which is used by one thread to query the interrupt status of another, does not change the interrupt status flag.

    By convention, any method that exits by throwing an InterruptedException clears interrupt status when it does so. However, it's always possible that interrupt status will immediately be set again, by another thread invoking interrupt.

    What you're seeing is that the thread gets interrupted, the method being exited is the join (actually join is implemented by calling Object.wait, so I would expect the stacktrace would show that wait is the method the exception is thrown from), and the flag gets cleared like the tutorial says.

    It's up to the handler of the exception to decide whether the thread's interrupt status flag should be set again or not. Unless the handler is coded to do something differently the default assumption is that the exception was handled and there's no need for the flag to be set anymore.

    The API documentation for Thread#interrupt is consistent with this:

    If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException.

    I have an answer that goes more into why interruption was designed this way here.