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

标签 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() 就足够了?

最佳答案

如您所说,不同之处在于,一种清除线程的中断状态,另一种不清除。既然您已经知道这一点,那么您真正要问的似乎是保持线程的中断状态是否重要。

首先必须确定检查中断状态(或处理 InterruptedException)的代码是否被视为线程的“所有者”。如果是这样,在某些有限的情况下,吞下(或只是不抛出)InterruptedException 以及中断状态可能是合适的,因为所有者正在实现线程的取消策略(Goetz, Java 并发实践,第 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 编译,编译器会给您一个有用的警告:

warning: [static] static method should be qualified by type name, Thread, instead of by an expression

一些其他工具可能会做类似的事情,例如 Eclipse,它将显示:

The static method interrupted() from the type Thread should be accessed in a static way

关于java - 为什么在实现 Runnable 时使用 Thread.currentThread().isInterrupted() 而不是 Thread.interrupted()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16916238/

相关文章:

java - Sybase 用于 Redhat Linux 的 BCP 实用程序

java - 无法使用 keycloak-admin-client 在 Keycloak 中创建用户

c# - 查看我的应用程序正在运行多少个线程?

java - 这个 64 位数字变量多线程规则在 Java 1.8 中仍然适用还是已经过时了?

Linux 中断并发

java - 如何每 5 分钟唤醒一次我的 Intent 服务

java - 将图像放入 webview 并适合其宽度

c - 使用共享条件变量的多个进程之间的 IPC

c - 模拟硬件中断

c - linux 内核模块在 100000 次中断后死掉