2

我正在阅读有关 Java 并发的本教程。链接文章中提供了有关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是静态的,因为它在 and 上运行,currentThread()并且Thread.isInterrupted是一个实例方法,因为它在Thread它被调用的实例上运行。

4

1 回答 1

3

检查中断标志状态有两种不同的方法。不幸的是,你应该使用的那个看起来不如你不应该使用的那个那么方便。

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

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

当抛出 InterruptedException 时,中断标志应该被清除,所以在这种情况下这会很方便。除非你正在做这样的事情(这应该很少见),否则永远不要使用这种方法。

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

Thread.currentThread().isInterrupted()

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

请注意,interrupted 是一个静态方法,它总是检查当前线程的中断状态,而 isInterrupted 是一个实例方法,因此您必须查找当前线程才能在其上调用此方法(或者您可以测试中断状态其他线程)。

使中断更容易使用导致代码更容易出错,因为人们在不阅读 api 文档的情况下采用更简单的方法。

于 2018-03-06T03:21:57.510 回答