以下处理InterruptedException的方法有什么区别?最好的方法是什么?
try{
//...
} catch(InterruptedException e) {
Thread.currentThread().interrupt();
}
OR
try{
//...
} catch(InterruptedException e) {
throw new RuntimeException(e);
}
编辑:我还想知道在哪些场景中使用这两个。
以下处理InterruptedException的方法有什么区别?最好的方法是什么?
try{
//...
} catch(InterruptedException e) {
Thread.currentThread().interrupt();
}
OR
try{
//...
} catch(InterruptedException e) {
throw new RuntimeException(e);
}
编辑:我还想知道在哪些场景中使用这两个。
当前回答
我想说,在某些情况下,什么都不做是可以的。可能不是默认情况下你应该做的事情,但如果没有办法发生中断,我不确定还能做什么(可能记录错误,但这不会影响程序流)。
一种情况是你有一个任务(阻塞)队列。如果你有一个守护线程处理这些任务,你自己不中断线程(据我所知,jvm不会中断守护线程在jvm关机),我看不到中断发生的方式,因此它可以被忽略。(我知道守护线程可能在任何时候被jvm杀死,因此在某些情况下是不合适的)。
编辑: 另一种情况可能是受保护的块,至少基于Oracle的教程: http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
其他回答
我想说,在某些情况下,什么都不做是可以的。可能不是默认情况下你应该做的事情,但如果没有办法发生中断,我不确定还能做什么(可能记录错误,但这不会影响程序流)。
一种情况是你有一个任务(阻塞)队列。如果你有一个守护线程处理这些任务,你自己不中断线程(据我所知,jvm不会中断守护线程在jvm关机),我看不到中断发生的方式,因此它可以被忽略。(我知道守护线程可能在任何时候被jvm杀死,因此在某些情况下是不合适的)。
编辑: 另一种情况可能是受保护的块,至少基于Oracle的教程: http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html
我只是想给大多数人和文章提到的最后一个选项。正如mR_fr0g所述,正确地处理中断是很重要的:
传播InterruptException 恢复线程中断状态
或者另外:
中断的自定义处理
根据您的情况以自定义方式处理中断并没有什么问题。由于中断是终止请求,而不是强制命令,因此完成额外的工作以允许应用程序优雅地处理请求是完全有效的。例如,如果一个线程正在睡觉,等待IO或硬件响应,当它接收到中断时,那么在终止线程之前优雅地关闭任何连接是完全有效的。
我强烈建议大家理解这个主题,但这篇文章是一个很好的信息来源:http://www.ibm.com/developerworks/java/library/j-jtp05236/
正确的默认选择是将InterruptedException添加到抛出列表中。中断表示另一个线程希望你的线程结束。这个请求的原因并不明显,完全是上下文相关的,所以如果你没有任何额外的知识,你应该假设这只是一个友好的关闭,任何避免关闭的事情都是一个不友好的响应。
Java will not randomly throw InterruptedException's, all advice will not affect your application but I have run into a case where developer's following the "swallow" strategy became very inconvenient. A team had developed a large set of tests and used Thread.Sleep a lot. Now we started to run the tests in our CI server, and sometimes due to defects in the code would get stuck into permanent waits. To make the situation worse, when attempting to cancel the CI job it never closed because the Thread.Interrupt that was intended to abort the test did not abort the job. We had to login to the box and manually kill the processes.
长话短说,如果您只是抛出InterruptedException,那么您就匹配了线程应该结束的默认意图。如果不能将InterruptedException添加到抛出列表中,我会将其包装在RuntimeException中。
There is a very rational argument to be made that InterruptedException should be a RuntimeException itself, since that would encourage a better "default" handling. It's not a RuntimeException only because the designers stuck to a categorical rule that a RuntimeException should represent an error in your code. Since an InterruptedException does not arise directly from an error in your code, it's not. But the reality is that often an InterruptedException arises because there is an error in your code, (i.e. endless loop, dead-lock), and the Interrupt is some other thread's method for dealing with that error.
如果你知道有合理的清理工作要做,那就去做。如果你知道一个更深层次的中断原因,你可以采取更全面的处理。
因此,总的来说,你的处理方式应该遵循以下列表:
默认情况下,添加到抛出。 如果不允许添加到抛出,则抛出RuntimeException(e)。(多个坏选项中的最佳选择) 只有当您知道中断的显式原因时,才能按需要处理。如果你的处理是在你的方法的本地,那么重置中断调用Thread.currentThread().interrupt()。
对我来说,关键的事情是:一个InterruptedException并不是什么出错了,它是线程在做你告诉它做的事情。因此,在RuntimeException中重新抛出它毫无意义。
In many cases it makes sense to rethrow an exception wrapped in a RuntimeException when you say, I don't know what went wrong here and I can't do anything to fix it, I just want it to get out of the current processing flow and hit whatever application-wide exception handler I have so it can log it. That's not the case with an InterruptedException, it's just the thread responding to having interrupt() called on it, it's throwing the InterruptedException in order to help cancel the thread's processing in a timely way.
因此,传播InterruptedException,或者智能地吃掉它(意思是在它将完成它要做的事情的地方)并重置中断标志。注意,当InterruptedException被抛出时,中断标志将被清除;Jdk库开发人员的假设是捕捉异常等同于处理异常,因此默认情况下该标志被清除。
所以第一种方法肯定更好,问题中的第二个例子是没有用的,除非你不期望线程实际上被中断,而中断它等于一个错误。
下面是我写的一个回答,描述了中断是如何工作的,并给出了一个例子。在示例代码中,您可以看到它使用InterruptedException来跳出Runnable的run方法中的while循环。
碰巧今天早上我在上班的路上读到了Brian Goetz的《Java并发实践》。基本上他说你应该做三件事中的一件
Propagate the InterruptedException - Declare your method to throw the checked InterruptedException so that your caller has to deal with it. Restore the Interrupt - Sometimes you cannot throw InterruptedException. In these cases you should catch the InterruptedException and restore the interrupt status by calling the interrupt() method on the currentThread so the code higher up the call stack can see that an interrupt was issued, and quickly return from the method. Note: this is only applicable when your method has "try" or "best effort" semantics, i. e. nothing critical would happen if the method doesn't accomplish its goal. For example, log() or sendMetric() may be such method, or boolean tryTransferMoney(), but not void transferMoney(). See here for more details. Ignore the interruption within method, but restore the status upon exit - e. g. via Guava's Uninterruptibles. Uninterruptibles take over the boilerplate code like in the Noncancelable Task example in JCIP § 7.1.3.