为什么吞咽InterruptedException确定Thread的子类?

在Brian Goetz 关于如何处理InterruptedException的文章中 ,有一段突出:

当你知道线程即将退出时,吞下一个中断是可以接受的。 只有当调用可中断方法的类是Thread的一部分而不是Runnable时,才会出现这种情况。

我不懂。 是什么原因与Runnable可能由线程池处理,而线程是你自己开始的东西?

基本上。 文章中表达的担忧是,如果你吞下中断exception,那么在堆栈中调用更高的代码将不会知道中断,可能导致不良行为。 如果你启动线程,那么你就知道调用堆栈中没有任何东西可以关注被中断,这个线程不会继续存在于线程池中,所以只需让线程死掉。

我讨厌InterruptedException,我认为它给已检查的exception一个坏名称,本文不会改变这种观点。 如果这个exception传递给调用堆栈非常重要,Runnable.run()应该在方法声明中声明它,这样你就可以简单地重新抛出它,或者它应该是一个未经检查的exception,出于同样的原因,SecurityException是未经检查的例外。

我喜欢的设计是如果你知道的话,如果它们被中断,那么方法会返回一个布尔值,但是这篇文章确实certificate了这不一定是实际的。

我认为扩展Thread是不必要的,因此实现Runnable是首选。

但重要的是代码知道线程将要退出。 如果您的代码是某些通用回调接口的一部分,那么您无法知道如何使用它。 您可以传递给线程池(实际上,我们可能应该使用池而不是在代码中的不适当的位置构造Thread )。 OTOH,通常Runnable是一个匿名的内部类,因此,在源代码级别,是知道发生了什么的封闭方法的一部分。

因此,如果线程即将退出,则重置当前线程上的中断状态是没有意义的,因为没有任何中断。

在某些时候,你会想说它已经中断了。 例如,线程池可以在任务中断后继续使用线程,尽管它们可能希望为尝试接收任务的调用者保留InterruptException

库通常不能正确处理中断。 IMO,中断没有合理的上下文。 没有它们,生活会变得更加简单,不幸的是,它们会让人感觉到它们的存在。

我同意其他人的不同之处在于你是否控制了该线程。 如果您扩展了一个Thread,那么您可以控制该线程。 另一方面,如果您的代码只是一个Runnable,它可能在您不拥有的借用线程(如线程池)上运行。 通过吃掉exception并且不恢复中断状态,您将使代码更高,无法识别并执行中断。

我认为,InterruptedException是一个经过检查的exception是一件好事。 InterruptedException是一种请求取消任务的方法。 假设有人以Runnable的forms编写了一个任务,该任务涉及一个抛出InterruptedException的阻塞方法。 如果它不是一个经过检查的exception,如果你没有小心,你可能不会想到对InterruptedException采取行动(从而取消)并进行自己的清理

 public class MyTask implements Runnable { public void run() { while (someCondition) { Object value = someBlockingQueue.take(); // act on the value and loop back } } } 

由于InterruptedException是一个经过检查的exception,我的任务应该如何响应中断(取消)是前端和中心。

 public class MyTask implements Runnable { public void run() { while (someCondition) { try { Object value = someBlockingQueue.take(); // act on the value and loop back } catch (InterruptedException e) { // I'm being cancelled; abort cleanUp(); // restore the interrupt Thread.currentThread().interrupt(); break; } } } }