Reputation: 6380
Consider the following JUnit test:
@Test
public void testSettingInterruptFlag() throws InterruptedException {
Thread blockingThread = new Thread(new Runnable() {
@Override
public synchronized void run() {
try {
wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
blockingThread.start();
blockingThread.interrupt();
blockingThread.join();
assertTrue(blockingThread.isInterrupted());
}
The test fails even though the interrupted status was set.
I've suspected that the line blockingThread.join();
resets the flag but even when replacing that line with Thread.sleep(3000);
the test still fails. Is this behaviour documented anywhere?
Upvotes: 10
Views: 1048
Reputation: 8297
This has been fixed in Java 14.
Thread.isInterrupted
returns true
if the thread was interrupted, even if the thread is not alive. See Oracle's release notes and JDK-8229516.
The specification for
java.lang.Thread::interrupt
allows for an implementation to only track the interrupt state for live threads, and previously this is what occurred. As of this release, the interrupt state of aThread
is always available, and if you interrupt a threadt
before it is started, or after it has terminated, the queryt.isInterrupted()
will return true.
The following paragraph has been added to the javadoc of Thread#interrupt
:
In the JDK Reference Implementation, interruption of a thread that is not alive still records that the interrupt request was made and will report it via
interrupted
andisInterrupted()
.
So the test in the question runs successfully on:
openjdk version "14.0.2" 2020-07-14
OpenJDK Runtime Environment (build 14.0.2+12)
OpenJDK 64-Bit Server VM (build 14.0.2+12, mixed mode)
The interruption flag is stored as a field in the Thread
class:
/* Interrupt state of the thread - read/written directly by JVM */
private volatile boolean interrupted;
and isInterrupted
method simply returns the flag:
public boolean isInterrupted() {
return interrupted;
}
previously it delegated to a native
isInterrupted(boolean)
method
Upvotes: 5
Reputation: 3913
From the JavaDocs: "A thread interruption ignored because a thread was not alive at the time of the interrupt will be reflected by this method returning false."
Your thread had not started yet when you called "Thread.interrupt()".
Making unit tests for concurrent systems is pretty tricky. You can make it slightly more robust by adding a delay into the test but that unfortunately slows down the test execution so you can not have a lot of them.
To make it fail safe you need to add a boolean flag to the thread class that tells the test that it has started and wait for that flag to be raised in a busy loop. Only then you can call interrupt and join.
Upvotes: 0
Reputation: 13535
what we see is that interrupted status of a thread is cleared when that thread finishes. It is not documented in http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html, so can be considered as a spec or implementation bug.
Upvotes: 5