Java 始终调用Thread.currentThread().interrupt();当捕捉到中断异常时?

Java 始终调用Thread.currentThread().interrupt();当捕捉到中断异常时?,java,multithreading,Java,Multithreading,国家: “只有当您知道线程即将退出时,才可以接受接受接受中断。只有当调用可中断方法的类是线程的一部分,而不是可运行的[…]时,才会发生这种情况。” 到现在为止,我总是为我的线程实现Runnable。给出如下可运行的实现: public class View() implements Runnable { @Overload public void run(){ Thread worker = new Thread(new Worker()); wo

国家:

“只有当您知道线程即将退出时,才可以接受接受接受中断。只有当调用可中断方法的类是
线程的一部分,而不是
可运行的
[…]时,才会发生这种情况。”

到现在为止,我总是为我的线程实现
Runnable
。给出如下
可运行的
实现:

public class View() implements Runnable {
    @Overload
    public void run(){
        Thread worker = new Thread(new Worker());
        worker.start();
        do{
            try{
                TimeUnit.SECONDS.sleep(3);
                updateView();
            }catch(InterruptedException e){
                worker.interrupt();
                // Thread.currentThread().interrupt();
                return;
            }
        }while(true);
    }

    protected void updateView(){
        // …
    }
}
是否真的需要调用
Thread.currentThread().interrupt()就在我的
返回之前语句?不
返回是否已执行干净的启动退出?叫它有什么好处?这篇文章指出应该这样做,因为否则“[…]调用堆栈上更高级别的代码将无法找到它[…]”。
thread.State.TERMINATED
中的线程在应用程序关闭时设置了中断标志,而没有中断标志的线程有什么好处?你能给我一个例子,在
Runnable
之外的代码出于合理的原因检查中断标志吗


顺便说一句,扩展
线程
而不是实现
可运行
,这是更好的代码设计吗?

它重置中断标志。这将更详细地介绍这个令人困惑的话题

在我的示例中,在捕获InterruptedException之后,我使用 Thread.currentThread().interrupt()立即中断 再穿一次。为什么这是必要的?当抛出异常时 中断标志被清除,因此如果有嵌套循环,则 在外部回路中造成故障


所以,如果您知道您的代码不会被其他组件使用,那么您就不需要重新中断。然而,我真的不会做那个小小的优化。谁知道你的代码将来将如何被使用/重用(即使是通过复制/粘贴),因此我会为每个中断重置标志。

我更喜欢扩展
线程
,因为它可以让你更好地理解线程在做什么,但不一定是更好的代码设计

正如Brian所说,它重置了中断标志,但这并不能说明什么。在您的情况下,它将不起任何作用,
视图
-线程将继续运行

中断线程时,标准过程是线程应停止运行。它不会自动执行此操作,一旦中断,您必须实现一种方法来停止它

使用内置功能有两个选项:

  • 将主循环置于
    中断异常的try块内。这样,当它被中断时,您将被抛出循环,方法将退出
  • 如果必须保存状态,则上述情况可能不好,因为它可能会损坏状态。或者,您可以设置interrupted标志(如抛出时所述)。重新中断它以中断线程

无论哪种方式,都必须检查while循环中的线程是否中断(while循环中的
!Thread.currentThread().isInterrupted()
-语句)或者它可能会/不会退出。您没有完成第一个选项之一,也没有检查标志,因此您的
视图
-线程在被中断后将继续运行。

以下是一个仅返回它还不够的示例:

public void doSomething1() {
  while (someCondition1()) {
    synchronized {
       try {
         this.wait();
       } catch (InterruptedException e) {
         return; // Should be Thread.currentThread().interrupt();
       }
    }
  }
}
public void doSomething2() {
  while (someCondition2()) {
    doSomething1();
  }
}
当异常抛出在下次执行doSomething1()时清除中断状态时,状态被清除,线程不会终止

真的有必要在我的
返回;
语句之前调用
线程.currentThread().interrupt();

作为一个观点,我总是这样做。我们都复制和粘贴代码,吞下中断是一个非常严重的问题,我通常都会这样做,即使线程即将死亡

return;
是否已经执行了足够干净的退出

如果您确定这是
run()
方法完成并且线程退出之前的最后一次返回,那么是的,这在技术上是不必要的。但是请参见上文。对于后代,
return;
不会对中断标志做任何事情

问题是您的
视图
类是否已被包装。您确定返回时您正在退出
线程
。可能有人正在委托它。AOP可能正在执行某种检测

调用它有什么好处?文章指出应该这样做,因为否则“[…]调用堆栈上更高级别的代码将无法找到它[…]”

一般来说,当您的代码被某种需要中断标志的包装代码(委托、AOP等)调用时,不要吞下中断是很重要的。如果吞下中断,包装器将无法使用它。但在这种情况下,没有任何好处

应用程序关闭时,如果线程处于thread.State.TERMINATED状态,并且在一个线程上设置了中断标志,那么该线程有什么好处

什么都没有。一旦线程退出,中断状态就毫无价值了。实际上,在线程死后,中断状态看起来甚至没有持续存在

Thread thread = new Thread(new Runnable() {
    public void run() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.out.println("caught");
        }
    }
});
thread.start();
thread.interrupt();
System.out.println(thread.isInterrupted());
thread.join();
System.out.println(thread.isInterrupted());
印刷品:

true
caught
false
您能给我一个例子,其中Runnable之外的代码出于合理的原因检查中断标志吗

我不能。线程的
run()
方法之外没有代码,除非有人在你不知情的情况下用其他代码包装你的runnable

如果您使用的是
ExecutorService
,则可能会发生这种情况,但在这种情况下,在作业运行之前,线程的中断状态会通过
wt.isInterrupted()
特别清除


同样,我们之所以要这么做,是因为它是一个好的模式,这在软件工程中很重要。

请看,普遍的共识是实现
Runnable
。扩展线程是…@assylas,没有人说这是一种不好的做法