Java Thread.interrupted和中断标志

问题描述 投票:2回答:1

我正在阅读关于Java并发的this文档。链接文章中提供了关于Thread.interrupted实施的片段。

中断机制使用称为中断状态的内部标志来实现。调用Thread.interrupt设置此标志。当线程通过调用静态方法Thread.interrupted来检查中断时,将清除中断状态。非静态isInterrupted方法,由一个线程用于查询另一个线程的中断状态,不会更改中断状态标志。按照惯例,任何通过抛出InterruptedException退出的方法都会在执行此操作时清除中断状态。但是,通过另一个调用中断的线程,总是可以立即再次设置中断状态。

这是相应的Javadoc

java.lang.Thread public static boolean interrupted()测试当前线程是否已被中断。此方法清除线程的中断状态。换句话说,如果要连续两次调用此方法,则第二次调用将返回false(除非当前线程在第一次调用已清除其中断状态之后且在第二次调用之前检查它时再次中断)。线程中断被忽略,因为在中断时线程不活动将被此方法反映返回false。返回:如果当前线程已被中断,则返回true;否则是假的。另见:isInterrupted()

在阅读了Thread.interrupted的这两个解释之后,我对中断标志是什么以及它被清除的地方感到困惑。像Thread.interrupted这样的函数不应该是幂等的而不是修改它被调用的对象的状态吗?我得知Thread.interrupted是静态的,因为它在currentThread()上运行,Thread.isInterrupted是一个实例方法,因为它在Thread实例上运行它被调用。

java multithreading interruption
1个回答
2
投票

有两种不同的方法可以检查中断的标志状态。不幸的是,你应该使用的那个不像你不应该使用的那个。

你不应该使用的是Thread#interrupted,因为它会重置标志。我认为对于你想要检测中断的非常狭窄的情况,interrupted()是一种方便的方法,如果被中断则清除标志并抛出InterruptedException:

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

当抛出InterruptedException时,应清除中断标志,因此在这种情况下这将是方便的。除非你正在做这样的事情(这应该是非常罕见的),不要使用这种方法。

您应该使用的方法是Thread#isInterrupted。它通常使用当前运行的线程调用,如

Thread.currentThread().isInterrupted()

此方法不会更改中断标志的状态,并且是您要检查中断时应使用的方法。

请注意,interrupted是一个静态方法,它始终检查当前线程的中断状态,而isInterrupted是一个实例方法,因此您必须查找当前线程才能在其上调用此方法。使中断更容易使用导致更容易出错的代码,因为人们在不阅读api文档的情况下采用更简单的方法。

© www.soinside.com 2019 - 2024. All rights reserved.