在Brian Goetz的article on how to handle InterruptedException中,有一段突出:
当你知道线程即将退出时,吞下一个中断是可以接受的。只有当调用可中断方法的类是Thread的一部分而不是Runnable时,才会出现这种情况。
我不懂。是什么原因与Runnable可能由线程池处理,而线程是你自己开始的东西?
答案 0 :(得分:4)
基本上。文章中表达的担忧是,如果你吞下中断异常,那么在堆栈中调用更高的代码将不会知道中断,可能导致不良行为。如果你启动线程,那么你就知道调用堆栈中没有任何东西可以关注被中断,这个线程不会继续存在于线程池中,所以只需让线程死掉。
我讨厌InterruptedException,我认为它给已检查的异常一个坏名称,本文不会改变这种观点。如果这个异常传递给调用堆栈非常重要,Runnable.run()应该在方法声明中声明它,这样你就可以简单地重新抛出它,或者它应该是一个未经检查的异常,出于同样的原因,SecurityException是未经检查的异常。
我最喜欢的设计是,如果你想知道它们被中断的话,方法会返回一个布尔值,但是这篇文章确实证明了那不一定是实用的。
答案 1 :(得分:3)
我认为延长Thread
是不必要的,因此优先实施Runnable
。
但重要的是代码知道线程将要退出。如果您的代码是某些通用回调接口的一部分,那么您无法知道如何使用它。您可以传递给线程池(实际上,我们可能应该使用池而不是在代码中的不适当的位置构建Thread
)。 OTOH,通常Runnable
是一个匿名的内部类,因此,在源级别,是知道发生了什么的封闭方法的一部分。
因此,如果线程即将退出,则重置当前线程上的中断状态是没有意义的,因为没有什么可以中断。
在某些时候,你会想说它已经中断了。例如,即使在任务中断后,线程池也可以继续使用线程,尽管他们可能希望为试图接收任务的调用者保留InterruptException
。
库通常不能正确处理中断。 IMO,中断没有合理的上下文。没有它们,生活会变得更加简单,不幸的是,它们会让人感觉到它们。
答案 2 :(得分:2)
我同意其他人的看法,不同之处在于您是否控制该线程。如果您扩展了一个Thread,那么您可以控制该线程。另一方面,如果您的代码只是一个Runnable,它可能在您不拥有的借用线程(如线程池)上运行。通过吃掉异常和而不是恢复中断状态,你就会剥夺代码更高的识别和处理中断的机会。
InterruptedException是一个经过检查的异常,我认为是一件好事。 InterruptedException是一种请求取消任务的方法。假设有人以Runnable的形式编写了一个任务,该任务涉及一个抛出InterruptedException的阻塞方法。如果它不是一个经过检查的例外,如果你不小心,你可能不会想到对InterruptedException采取行动(从而取消)并且你自己的清理。
public class MyTask implements Runnable {
public void run() {
while (someCondition) {
Object value = someBlockingQueue.take();
// act on the value and loop back
}
}
}
由于InterruptedException是一个经过检查的异常,我的任务应如何响应中断(取消)是前端和中心。
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;
}
}
}
}