问题 为什么在实现Runnable时使用Thread.currentThread()。isInterrupted()而不是Thread.interrupted()?


在stackoverflow上,我经常看到使用 Thread.currentThread().isInterrupted()。实施时 Runnable 并在while循环中使用它,如下所示:

public void run() {
  while(!Thread.currentThread().isInterrupted()) { ... }
}

使用有什么不同 Thread.interrupted() (除了那个 interrupted 标志在使用时被清除 interrupted())?

我也见过 Thread.currentThread().interrupted()。这是使用它的正确方法,或者是 Thread.interrupted() 足够?


3658
2018-06-04 11:06


起源

stackoverflow.com/questions/4801317/... - itzhaki
@itzhaki这不是一个有用的链接。这是关于 interrupt 方法。 - Marko Topolnik


答案:


正如你所说的那样,区别在于,一个人清除了线程的中断状态,而另一个则没有。既然你已经知道了,那么你真正想要的是保持线程中断状态是否重要。

首先必须确定代码是否检查中断状态(或处理一个 InterruptedException)被认为是线程的“所有者”。如果是这样的话,在某些有限的情况下,吞下(或者不扔)是适当的 InterruptedException 因为所有者正在实施线程的取消政策(Goetz, Java并发实践,p。 143)。

但在绝大多数情况下,包括一个 Runnable,有问题的代码是  线程所有者和 一定不 吞下取消状态。在这种情况下,您有两个选择:

  • 保持线程中断状态清零但抛出 InterruptedException。 (这是什么 Thread.sleep() 确实。)
  • 保留中断状态。

在一个案例中 Runnable,你不能抛出一个检查过的异常,因为 run() 没有宣布这样做。 (反过来,我认为它的设计是这样的,因为通常没有人会抓住它。)所以你唯一的选择就是保留取消状态。

鉴于上述解释,让我回到你的直接问题。首先,如果要检查取消状态并保留它,则更容易编写

if (Thread.currentThread().isInterrupted()) doSomething;

if (Thread.interrupted()) {
    Thread.currentThread().interrupt();
    doSomething;
}

此外,如您原来的问题,如果您使用过 Thread.interrupted() 作为一个条件 while 循环,循环中断后你不知道它是否因为终止而终止 Thread.interrupted() 回 true 或其他一些条件改变或a break 声明跑了。所以在那种情况下使用 Thread.currentThread().isInterrupted() 真的是你的 只要 选项。 (当然你也可以编写循环代码 只要 它会退出的原因是线程被中断了,但是你的代码会变得脆弱,因为在循环之后你必须重新中断线程,如果其他人后来出现并改变了代码,那么也会突破某些循环其他原因,当你没有最初中断线程时,你就会打断它。)

对于你的第二个问题,正如其他人所说, 决不 使用 Thread.currentThread().interrupted() 因为它有误导性。以来 interrupted() 是一个静态方法,在这种情况下,编译器会在您编译时为您提供有用的警告 -Xlint

警告:[静态]静态方法应该通过类型名称Thread来限定,而不是通过表达式来限定

其他一些工具也可能类似,例如Eclipse,它将显示:

应该以静态方式访问Thread类型的static()静态方法


7
2017-09-05 14:42





只是回答你问题的最后部分......

我也见过 Thread.currentThread().interrupted()。这是使用它的正确方法,或者是 Thread.interrupted() 足够?

在纯函数术语中,它们的含义完全相同。

但就可读性而言,

    Thread.currentThread().interrupted()

做到了  就像你正在调用一个实例方法......但你不是。因此,

    Thread.interrupted()

更好。当然不要这样做:

    Thread someThread = ...
    someThread.interrupted()

好像 你会测试 someThread, 但你是 其实 测试当前线程。非常误导!


6
2018-06-04 11:14



interrupted()清除中断状态,而isInterrupted()则不... - sjlee
@sjlee - 我的回答没有谈到 isInterrupted。请看第一句。 - Stephen C


差异非常微妙,通常无关紧要。你可以根据需要设置或清除中断的标志。甚至没有标准的做法说“使用一个而不使用另一个”。

重点是要知道你正在用中断的标志做什么:把它留在一个你没有特别想要的状态  只是微妙的区别。

决不 使用 Thread.currentThread().interrupted()。这只会产生误导,特别是如果你有的话 someOtherThread.interrupted()


3
2018-06-04 11:10



在我正在看的文档中, interrupted 是静态的,所以不会把它称为 Thread.currentThread().interrupted() 没必要吗? - cmbaxter
这不仅仅是不必要的,但我不认为OP的问题主要是关于这种差异。这更像是一个侧面点。 - Marko Topolnik


使用有什么不同 Thread.interrupted() (除了使用时清除中断的标志 interrupted())?

不,但这是一个非常深刻的区别。如果你只是在你的例子中使用它,在一个单独的内部 while 循环在线程中 run 方法,这样的 run 当线程中断时,方法退出,然后没有区别,但在其他情况下可能会有。例如,设想嵌套循环,每个循环检查中断状态(内部循环清除状态,然后外部检查它...)

至于之间的区别 Thread.currentThread().interrupted() 与 Thread.interrupted(),没有功能差异,但后者更短,所以使用它。


0
2018-06-04 11:12



前者也会在许多具有默认配置的IDE中生成警告,这是一个非常好的警告。 - Marko Topolnik
@marko,为什么警告它是否有任何不同之处是一件好事? - Christian
这是因为它通常表示程序员错误的意图是调用实例方法,并且任何未来的读者都可能误解了这种表达式的含义。 - Marko Topolnik