Thread.isInterrupted()在线程终止后返回false

lpa*_*zic 9 java concurrency

考虑以下JUnit测试:

@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());
}
Run Code Online (Sandbox Code Playgroud)

即使设置了中断状态,测试也会失败.我怀疑该行blockingThread.join();重置了标志,但即使用Thread.sleep(3000);测试替换该行仍然失败.这种行为记录在哪里吗?

Ale*_*dov 5

我们看到的是线程的中断状态在该线程完成时被清除。它没有记录在http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html 中,因此可以被视为规范或实现错误。


cac*_*co3 4

Java 14 中已修复此问题。

Thread.isInterruptedtrue如果线程被中断,则返回,即使线程不活动。请参阅 Oracle 的发行说明JDK-8229516

规范java.lang.Thread::interrupt允许实现仅跟踪活动线程的中断状态,而以前这就是发生的情况。从此版本开始,a 的中断状态始终Thread可用t,并且如果您在线程启动之前或终止之后中断线程t.isInterrupted()true。

以下段落已添加到 javadoc 中Thread#interrupt

在 JDK 参考实现中,不活动的线程的中断仍然记录发出了中断请求,并将通过以下方式报告:interrupted和报告isInterrupted()

因此问题中的测试成功运行在:

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)
Run Code Online (Sandbox Code Playgroud)

中断标志作为字段存储在Thread类中:

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)
Run Code Online (Sandbox Code Playgroud)

isInterrupted只是返回标志:

public boolean isInterrupted() {
    return interrupted;
}
Run Code Online (Sandbox Code Playgroud)

之前它委托给一个native isInterrupted(boolean)方法