In this program, a thread tries to interrupt itself and then
checks whether it succeeded. What does the program print?
public class SelfInterruption { public static void main(String[] args) { Thread.currentThread().interrupt(); if (Thread.interrupted()) { System.out.println("Interrupted: " + Thread.interrupted()); } else { System.out.println("Not interrupted: " + Thread.interrupted()); } } }
Solution 84: Rudely Interrupted
Although it is
not common for a thread to interrupt itself, it isn't unheard of, either. When a
method catches an InterruptedException and is not prepared to deal with
it, the method usually rethrows the exception. Because it is a checked
exception, a method can rethrow it only if the method declaration permits. If
not, the method can "reraise" the exception without rethrowing it, by
interrupting the current thread. This works fine, so our program should have no
trouble interrupting itself. Therefore, the program should take the first branch
of the if statement and print Interrupted: true. If you ran
the program, you found that it doesn't. It doesn't print Not interrupted:
false, either; it prints Interrupted: false.
It looks as if the program can't make up its mind about whether
the thread was interrupted. Of course, this makes no sense. What really happened
was that the first invocation of THRead.interrupted returned
true and cleared the interrupted status of the thread, so the second
invocation—in the then branch of the if-then-else
statement—returned false. Calling
Thread.interrupted always clears the interrupted status of the current
thread. The method name gives no hint of this behavior and, as of release
5.0, the one-sentence summary in the documentation is equally misleading: "Tests
whether the current thread has been interrupted" [Java-API]. Therefore, it is understandable
that many programmers are unaware that Thread.interrupted has any
effect on the interrupted status of the thread.
The THRead class has two methods to query the
interrupted status of a thread. The other one is an instance method named
isInterrupted, and it does not clear the
interrupted status of the thread. If rewritten to use this method, the program
produces the expected output of Interrupted: true:
public class SelfInterruption { public static void main(String[] args) { Thread.currentThread().interrupt(); if (Thread.currentThread().isInterrupted()) { System.out.println("Interrupted: " + Thread.currentThread().isInterrupted()); } else { System.out.println("Not interrupted: " + Thread.currentThread().isInterrupted()); } } }
The lesson of this puzzle is: Don't
use THRead.interrupted unless you want to clear the interrupted status
of the current thread. If you just want to query it, use
isInterrupted instead. The lesson for API designers is that methods
should have names that describe their primary functions. Given the behavior of
THRead.interrupted, it should have been named
clearInterruptStatus. Its return value is secondary to the state change
it effects. Especially when a method has a name that is less than perfect, it is
important that its documentation clearly describe its behavior.
No comments:
Post a Comment
Your comments are welcome!