我正在浏览有关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
实例上运行它被调用
答案 0 :(得分:2)
有两种不同的方法可以检查中断的标志状态。不幸的是,你应该使用的那个不像你不应该使用的那个。
你不应该使用的是Thread#interrupt,因为它会重置标志。我认为对于你想要检测中断的非常狭窄的情况,interrupted()是一种方便的方法,如果被中断则清除标志并抛出InterruptedException:
if (Thread.interrupted()) {
throw new InterruptedException();
当抛出InterruptedException时,应清除中断标志,因此在这种情况下这将是方便的。除非你正在做这样的事情(这应该是非常罕见的),不要使用这种方法。
您应该使用的方法是Thread#isInterrupted。它通常使用当前运行的线程调用,如
Thread.currentThread().isInterrupted()
此方法不会更改中断标志的状态,并且只要您想检查中断,就应该使用该方法。
请注意,interrupt是一个静态方法,它总是检查当前线程的中断状态,而isInterrupted是一个实例方法,因此您必须查找当前线程才能在其上调用此方法。使中断更容易使用导致更容易出错的代码,因为人们在不阅读api文档的情况下采用更简单的方法。