2

I'm going through this tutorial on Java concurrency. There's a snippet provided in the linked article regarding the implementation of Thread.interrupted.

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.

And this is the corresponding Javadoc

java.lang.Thread public static boolean interrupted() Tests whether the current thread has been interrupted. The interrupted status of the thread is cleared by this method. In other words, if this method were to be called twice in succession, the second call would return false (unless the current thread were interrupted again, after the first call had cleared its interrupted status and before the second call had examined it). A thread interruption ignored because a thread was not alive at the time of the interrupt will be reflected by this method returning false.

Returns: true if the current thread has been interrupted; false otherwise.

See Also: isInterrupted()

After reading both of these explanations of Thread.interrupted, I'm confused about what the interruption flag is and where it is being cleared. Shouldn't a function like Thread.interrupted be idempotent and not modify the state of the of the object it's being called on? I get that the Thread.interrupted is static because it operates on the currentThread() and Thread.isInterrupted is an instance method because it operates on the Thread instance it's being called on.

user207421
  • 305,947
  • 44
  • 307
  • 483
Carpetfizz
  • 8,707
  • 22
  • 85
  • 146
  • 3
    I also hate it that this method clears the flag although its name doesn't indicate it at all. I always use isInterrupted(). Other that that, the flag is cleared when interrupted() is called, or, by convention, when an InterruptedException is thrown (by Thread.sleep(), Object.wait(), etc.) – JB Nizet May 12 '17 at 15:57
  • But, since you might to restore your program to a normal flow after the InterruptedException, the same thread needs a refresh mechanism for interruption again. Why is the idempotency required then? Isn't it a natural behavior? – Manish Kumar Sharma May 12 '17 at 16:06
  • @pulp_fiction just out of naive intuition it seems like it would make more sense to set the flag when `interrupt` is called and reset the flag with `start` is called – Carpetfizz May 12 '17 at 16:15
  • But once a thread finishes execution(you don't block, sleep it or anything), its done for. There is no calling start() again. That means, there is on point of "resetting" the flag. While, InterruptedException is a checked one so you have the liberty to "resume" the flow to a stable state. With naive intuition too, resetting of flag on start() seems non-thinkable. What do you say? – Manish Kumar Sharma May 12 '17 at 16:19
  • I think that's starting to make sense for threads that are literally dead. I guess my confusion comes from the fact that you have to call `isInterrupted` to switch the flag – Carpetfizz May 12 '17 at 16:34
  • isInterrupted() doesn't switch the flag. interrupted() clears it and returns its previous value. interrupt() sets the flag. – JB Nizet May 12 '17 at 16:46
  • @pulp_fiction I think you're confused about how interruption works. Once a thread is interrupted it's not supposed to return to a normal flow. It must propagate the flag up the call stack so the thread can be terminated. – shmosel Mar 06 '18 at 03:49

1 Answers1

3

There are two different methods that check the interrupted flag status. Unfortunately, the one you should use is less convenient-looking than the one you shouldn’t.

The one you shouldn’t use is Thread#interrupted, because it resets the flag. I think that interrupted() is a convenience method for the very narrow case where you want to detect interruption, and if interrupted clear the flag and throw InterruptedException:

if (Thread.interrupted()) {
    throw new InterruptedException();

When throwing InterruptedException the interrupt flag should be cleared, so in this case this would be convenient. Unless you are doing something like this (which should be pretty rare) do not use this method, ever.

The method you should use is Thread#isInterrupted. It is typically called using the currently-running thread, like

Thread.currentThread().isInterrupted()

This method does not change the status of the interrupt flag and is the one you should be using whenever you want to check for interruption.

Note that interrupted is a static method that always checks the interrupt status of the current thread, while isInterrupted is an instance method so that you have to look up the current thread in order to call this method on it (or you can test the interrupted status of other threads).

Making interrupted easier to use has resulted in more error-prone code as people take the easier method without reading the api docs.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276