如果我不是,那谁正在调用Java Thread interrupt()方法?

Syn*_*r0r 82 java multithreading exception-handling exception

我已经阅读并重新阅读了Java Concurrency in Practice,我已经阅读了几个关于这个主题的线程,我已经阅读了IBM文章处理InterruptedException但是有些东西我根本没有抓到我认为可以打破的东西分为两个问题:

  1. 如果我自己永远不会打断其他线程,那么什么可以触发InterruptedException

  2. 如果我从未使用interrupt()中断其他线程(因为我正在使用其他方法来取消我的工作线程,比如毒丸和while(!取消)样式循环[如JCIP中所解释的那样]),那么InterruptedException是什么意思?抓到一个我该怎么办?关闭我的应用程序?

Ste*_*n C 49

线程中断机制是让(协作)线程响应请求以停止它正在做什么的首选方法.任何线程(包括我认为的线程本身)都可以调用interrupt()Thread.

在实践中,正常的用例interrupt()涉及某种框架或管理器告诉某些工作者线程停止他们正在做的事情.如果工作线程是"中断感知",它将注意到它已经通过异常中断,或者通过定期检查其中断标志.在注意到它被中断后,一个表现良好的线程会放弃它正在做的事情并结束自己.

假设使用上述用例,如果代码在Java框架或某个工作线程中运行,则可能会中断您的代码.当它被中断时,你的代码应该放弃它正在做的事情,并以最合适的方式使自己结束.根据代码的调用方式,可以通过返回或抛出一些适当的异常来完成.但它可能不应该打电话System.exit().(您的应用程序不一定知道它被中断的原因,并且它当然不知道是否有其他线程需要被框架中断.)

另一方面,如果您的代码不是设计为在某个框架的控制下运行,您可能会认为这InterruptedException是一个意外的异常; 即一个bug.在这种情况下,您应该像处理其他错误一样处理异常; 例如,将其包装在未经检查的异常中,并在处理其他意外未检查异常的同一点捕获并记录它.(或者,您的应用程序可以简单地忽略中断并继续执行它正在执行的操作.)


1)如果我自己从未打断过其他线程,那么什么可以触发InterruptedException?

一个例子是如果您的Runnable对象使用an执行ExecutorServiceshutdownNow()在服务上调用.理论上,任何第三方线程池或线程管理框架都可以合法地执行此类操作.

2)如果我从未使用interrupt()中断其他线程......那么它InterruptedException意味着什么?抓到一个我该怎么办?关闭我的应用程序?

您需要分析代码库以确定interrupt()调用的内容和原因.一旦你想到了这一点,你就可以弄清楚你的<<应用程序的一部分需要做什么.

直到你知道为什么InterruptedException被抛出,我建议把它当作一个难以理解的错误; 例如,将堆栈跟踪打印到日志文件并关闭应用程序.(显然,这并不总是正确的答案......但重点是这是"一个bug",需要引起开发人员/维护人员的注意.)

3)我如何找出谁/什么叫interrupt()

对此没有好的答案.我能建议的最好的方法是在上面设置断点Thread.interrupt()并查看调用堆栈.

  • >任何线程都可以在线程上调用interrupt() - 来自JCiP(7.1.2.中断策略):"因为每个线程都有自己的中断策略,所以你不应该中断*一个线程,除非你知道中断对该线程意味着什么" (3认同)

Bri*_*new 12

如果您决定将代码与其他库集成,他们可以调用interrupt()您的代码.例如,如果您决定将来在ExecutorService中执行您的代码,那么可能会强制关闭interrupt().

简单的说,我会考虑不只是在您的代码运行,现在,而是在什么情况下,可能在将来运行.你要把它放在图书馆吗?一个容器?其他人将如何使用它?你要重复使用吗?


小智 9

正如其他人所指出的那样,中断线程(实际上,中断阻塞呼叫)通常用于干净地退出或取消正在进行的活动.

但是,您不应该InterruptedException单独将其视为"退出命令".相反,您应该将中断视为控制线程运行状态的一种方法,与此类似Object.notify().在你从一个呼叫起床后检查当前的状态,以同样的方式Object.wait()(你不要以为唤醒意味着你的等待条件成立的情况),与中断被碰一碰后,你应该检查为什么你被打断.通常有一种方法可以做到这一点.例如,java.util.concurrent.FutureTask有一个isCancelled()方法.

代码示例:

public void run() {
    ....
    try {
        .... // Calls that may block.
    } catch (InterruptedException e) {
        if (!running) {  // Add preferred synchronization here.
            return; // Explicit flag says we should stop running.
        }
        // We were interrupted, but the flag says we're still running.
        // It would be wrong to always exit here. The interrupt 'nudge'
        // could mean something completely different. For example, it
        // could be that the thread was blocking on a read from a particular
        // file, and now we should read from a different file.
        // Interrupt != quit (not necessarily).
    }
    ....
}
public void stop() {
    running = false; // Add preferred synchronization here.
    myThread.interrupt();
}
Run Code Online (Sandbox Code Playgroud)