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

时间:2013-06-04 11:06:54

标签: java multithreading interrupt runnable

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

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

使用Thread.interrupted()有什么不同(使用interrupted时清除interrupted()标志除外)?

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

4 个答案:

答案 0 :(得分:7)

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

首先必须确定检查中断状态(或处理InterruptedException)的代码是否被视为线程的“所有者”。如果是这样,在某些有限的情况下,可能适合吞下(或者不抛出)InterruptedException以及中断状态,因为所有者正在实现线程的取消策略(Goetz, Java Concurrency in练习,第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或其他一些条件已更改或break语句已运行。因此,在这种情况下使用Thread.currentThread().isInterrupted()实际上是您的唯一选项。 (当然你也可以对循环进行编码,使得它将退出的唯一原因是线程被中断,但是你的代码将是脆弱的,因为在循环之后你必须重新中断线程如果其他人后来出现并且由于某些其他原因而改变了代码以便突破循环,那么当它最初没有被中断时你就会中断该线程。)

对于您的第二个问题,正如其他人所说,从不使用Thread.currentThread().interrupted(),因为它具有误导性。由于interrupted()是一个静态方法,在这种情况下,如果使用-Xlint进行编译,编译器会给出一个有用的警告:

  

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

来限定

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

  

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

答案 1 :(得分:6)

回答问题的最后部分...

  

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

在纯粹的功能性术语中,它们的含义完全相同。

但就可读性而言,

    Thread.currentThread().interrupted()

使看起来就像你正在调用一个实例方法......但你不是。因此,

    Thread.interrupted()

更好。当然不要这样做:

    Thread someThread = ...
    someThread.interrupted()

看起来像你要测试someThread,但你实际测试当前线程。非常误导!

答案 2 :(得分:3)

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

要点是要知道你正在对被打断的旗帜做什么:把它留在一个你没有特意打算的状态下肯定只会产生微妙的差别。

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

答案 3 :(得分:0)

  

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

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

至于Thread.currentThread().interrupted()Thread.interrupted()之间的差异,没有功能差异,但后者更短,因此请使用它。