以下处理InterruptedException的方法有什么区别?最好的方法是什么?

try{
 //...
} catch(InterruptedException e) { 
   Thread.currentThread().interrupt(); 
}

OR

try{
 //...
} catch(InterruptedException e) {
   throw new RuntimeException(e);
}

编辑:我还想知道在哪些场景中使用这两个。


当前回答

对我来说,关键的事情是:一个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循环。

其他回答

我只是想给大多数人和文章提到的最后一个选项。正如mR_fr0g所述,正确地处理中断是很重要的:

传播InterruptException 恢复线程中断状态

或者另外:

中断的自定义处理

根据您的情况以自定义方式处理中断并没有什么问题。由于中断是终止请求,而不是强制命令,因此完成额外的工作以允许应用程序优雅地处理请求是完全有效的。例如,如果一个线程正在睡觉,等待IO或硬件响应,当它接收到中断时,那么在终止线程之前优雅地关闭任何连接是完全有效的。

我强烈建议大家理解这个主题,但这篇文章是一个很好的信息来源:http://www.ibm.com/developerworks/java/library/j-jtp05236/

碰巧今天早上我在上班的路上读到了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.

你想做什么?

当一个线程正在等待或休眠,而另一个线程使用thread类中的中断方法中断它时,就会抛出InterruptedException。因此,如果捕捉到这个异常,就意味着线程已被中断。通常没有必要调用Thread.currentThread().interrupt();同样,除非您想从其他地方检查线程的“中断”状态。

关于抛出RuntimeException的其他选项,这似乎不是一件非常明智的事情(谁来捕捉这个?如何处理?)但如果没有额外的信息,很难透露更多信息。

对我来说,关键的事情是:一个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循环。

我想说,在某些情况下,什么都不做是可以的。可能不是默认情况下你应该做的事情,但如果没有办法发生中断,我不确定还能做什么(可能记录错误,但这不会影响程序流)。

一种情况是你有一个任务(阻塞)队列。如果你有一个守护线程处理这些任务,你自己不中断线程(据我所知,jvm不会中断守护线程在jvm关机),我看不到中断发生的方式,因此它可以被忽略。(我知道守护线程可能在任何时候被jvm杀死,因此在某些情况下是不合适的)。

编辑: 另一种情况可能是受保护的块,至少基于Oracle的教程: http://docs.oracle.com/javase/tutorial/essential/concurrency/guardmeth.html