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

Chr*_*ian 11 java multithreading interrupt runnable

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

public void run() {
  while(!Thread.currentThread().isInterrupted()) { ... }
}
Run Code Online (Sandbox Code Playgroud)

是否有任何不同使用Thread.interrupted()(除了interrupted使用时清除标志interrupted())?

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

Cha*_*N B 7

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

首先必须确定检查中断状态(或处理InterruptedException)的代码是否被视为线程的"所有者".如果是这样,在某些有限的情况下,InterruptedException由于所有者正在实现线程的取消策略(Goetz,Java Concurrency in Practice,p.143),因此吞下(或者不抛出)以及中断状态是合适的.

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

  • 保持线程中断状态清除但抛出InterruptedException.(这是做什么的Thread.sleep().)
  • 保留中断状态.

在a的情况下Runnable,您不能抛出已检查的异常,因为run()未声明这样做.(反过来,我认为它的设计是这样的,因为通常没有人会抓住它.)所以你唯一的选择就是保留取消状态.

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

if (Thread.currentThread().isInterrupted()) doSomething;
Run Code Online (Sandbox Code Playgroud)

if (Thread.interrupted()) {
    Thread.currentThread().interrupt();
    doSomething;
}
Run Code Online (Sandbox Code Playgroud)

此外,与原始问题一样,如果您Thread.interrupted()while循环中用作条件,则在循环中断之后您将不知道它是否因为Thread.interrupted()返回true或其他条件已更改或break语句运行而终止.所以在这种情况下使用Thread.currentThread().isInterrupted()真的是你唯一的选择.(当然你也可以对循环进行编码,使得它退出的唯一原因是线程被中断,但是你的代码会很脆弱,因为在循环之后你必须重新中断线程,如果其他人后来出现了并且由于某些其他原因而改变了代码以使其脱离循环,然后在最初未被中断时中断线程.)

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

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

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

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


Ste*_*n C 6

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

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

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

但就可读性而言,

    Thread.currentThread().interrupted()
Run Code Online (Sandbox Code Playgroud)

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

    Thread.interrupted()
Run Code Online (Sandbox Code Playgroud)

更好.当然不要这样做:

    Thread someThread = ...
    someThread.interrupted()
Run Code Online (Sandbox Code Playgroud)

看起来像你会被测试someThread,但你实际上是测试当前线程.非常误导!

  • interrupted()清除中断状态,而isInterrupted()则不... (2认同)