为什么 Thread.interrupted() 不能用 Thread.currentThread() 调用。中断?

Why is Thread.interrupted() not possible to call with Thread.currentThread().interrupted?

我决定修改一些旧的多线程概念。我遇到了 中断方法 。我读到了方法 isInterrupted()interrupted() 之间的区别。重点是 interrupted() 重置标志,isInterrupted() 不会。

我开始编码并注意到以下内容。方法 interrupted() 必须与 Thread 的 'prefix' 一起使用,而方法 isInterrupted() 必须与 Thread.currentThread() 的 'prefix' 一起使用。我想知道为什么。演示:

Thread.interrupted(); //compiles
Thread.currentThread().interrupted(); //doesn't compile

Thread.currentThread().isInterrupted(); //compiles
Thread.isInterrupted(); //doesn't compile

总而言之,谁能告诉我为什么他们有不同的电话? Thread.Thread.currentThread() 有什么区别?我的意思是,当我调用 Thread. 时,它应该直接 'focus' 那个 线程对象 的所有内容,所以我看不出在 [=] 中的任何地方使用 Thread.currentThread() 31=]Java。有人可以解决我的困惑吗?

interrupted() 是一个静态方法。

对于静态方法,通常的调用方式是这样的:

TypeTheMethodIsIn.staticMethod();

将此与只能像这样调用的 non-static 方法进行对比:

(expression of a type of the object containing the method).instanceMethod();

从技术上讲,您可以用第二种方式调用静态方法,但这完全没有意义(没有对该类型进行运行时查找),并且所有 linter 工具,包括 javac 本身,都会告诉您将其关闭。你应该注意这些。

Thread 的 interrupted() 方法是静态的。 Thread的isInterrupted()方法不是。

重点应该很清楚:检查中断标志是您可以对任何您喜欢的线程执行的操作。然而,清除它?您只能对自己的线程执行此操作。

在某些时候,我们正在研究 API 的程序员在编写程序当天的感受和想法,我和 SO 上的任何其他人都无法给你一个合理的答案。但是我们可以深入研究为什么他们可能会这样做。

假设你不应该修改其他线程的中断标志,只能修改你自己的,它可能是这样的:Thread.currentThread().clearInterruptedFlag(),但现在 currentThread() 完全是多余的;尝试在任何其他线程上调用它,然后您必须抛出异常,以确保线程只能清除自己的标志。

另一种方法是任何线程都可以清除任何其他线程的标志或它自己的标志,但这完全没有意义。提高该标志的目的是让该线程中的代码最终偶然发现它并退出或尽快停止某些阻塞进程。

那么为什么没有方法可以轻松检查自己的标志而不清除它呢?

再次,API设计。这有什么意义?

这就是你应该如何使用中断标志:

  1. 如果您的线程的中央阻塞性质是基于某种 CPU 冻结操作(定义为:核心库中指定抛出 InterruptedException 的任何内容,例如 obj.wait, Thread.sleep, yield, 等),你几乎不需要做任何事情。如果在您的 CPU 上出现了中断标志,请完全忽略它;很快(很快)您的线程将执行其中一个 'make the CPU freeze' 方法,例如 Thread.sleep,并且所有这些方法的实现首先检查标志并将 立即 抛出 InterruptedException 而无需冻结 CPU 如果他们注意到它被提升(并且他们立即降低该标志,以及。要么标志升起,要么 InterruptedEx 被抛出,永远不会两者)。哪个应该结束你的方法。 (如果您正在捕获 InterruptedException 并忽略它,请不要那样做)。

  2. 如果您的线程的性质是阻塞但未指定,则取决于体系结构。例如,如果您正在等待从网络套接字读取数据,谁知道会发生什么。要么标志被忽略并且您对此无能为力,要么 read() 调用或您正在做的任何事情都会抛出 IOException。它不能抛出 InterruptedException - 该方法不允许这样做。旗帜不会升起。

  3. 如果你的线程的性质是将时间花在主动操作上,例如,你正在开采比特币并且你所做的就是无休止地旋转 CPU ,哈希算法在一起,然后开箱即用地中断这样的线程什么都不做。然而,这样的线程很可能有某种 while 循环。您需要做的就是检查中断标志。如果启动,则退出。这取决于你如何:要么扔东西,要么,只是.. 退出。彻底结束 @Override public void run() {} 的代码。嘿,你提出了那个中断,你来决定它是什么意思。

#3 的关键点是在这两种情况下都应降低该标志,因为如果它保持升高并且您的代码回落到 'this thread is now over' 而不是 'I relinquish control back to my caller',那将是非常令人惊讶的如果该标志已升起。

因此,您最终会编写如下代码:

Runnable r = () -> {
    while (!Thread.interrupted()) {
        mineNextHash();
    }
};

简短、干净、切题。简单易行。