This IBM developerWorks article州:
“当你知道线程即将退出时,吞下一个中断是可以接受的。仅当调用可中断方法的类是
Thread
的一部分而不是Runnable
[...]“的一部分时,才会出现此情况。
我现在总是为我的线程实现Runnable
。给出Runnable
这样的实现:
public class View() implements Runnable {
@Overload
public void run(){
Thread worker = new Thread(new Worker());
worker.start();
do{
try{
TimeUnit.SECONDS.sleep(3);
updateView();
}catch(InterruptedException e){
worker.interrupt();
// Thread.currentThread().interrupt();
return;
}
}while(true);
}
protected void updateView(){
// …
}
}
是否真的有必要在Thread.currentThread().interrupt();
声明之前致电return;
? return;
是否已经执行干净的enaugh退出?叫它有什么好处?文章指出应该这样做,因为否则“[......]调用堆栈上面的代码将无法找到它[...]”。在应用程序关闭时,如果没有它,则Thread.State.TERMINATED
中的线程设置超过一个线程的好处是什么?你能给我一个例子,Runnable
以外的代码是否有明智的理由检查中断的旗帜?
Thread
而不是实施Runnable
是一种更好的代码设计吗?
答案 0 :(得分:10)
重置中断标志。这个JavaSpecialists newsletter更详细地介绍了这个令人困惑的话题。
在我的例子中,在我捕获InterruptedException之后,我使用了 Thread.currentThread()。interrupt()立即中断了 线程再次。为什么这有必要?当抛出异常时, 中断标志被清除,所以如果你有嵌套循环,你会 导致外循环出现问题
因此,如果您知道您的代码不会被其他组件使用,那么您不需要重新中断。但是我真的不会做那个小小的优化。谁知道将来如何使用/重用您的代码(即使通过复制/粘贴),因此我会为每个中断重置标志。
答案 1 :(得分:3)
这是一个返回它还不够的例子:
public void doSomething1() {
while (someCondition1()) {
synchronized {
try {
this.wait();
} catch (InterruptedException e) {
return; // Should be Thread.currentThread().interrupt();
}
}
}
}
public void doSomething2() {
while (someCondition2()) {
doSomething1();
}
}
当异常throw在下次执行doSomething1()时清除中断状态时,状态被清除,线程不会终止。
答案 2 :(得分:1)
我更喜欢扩展Thread
,因为它可以让您更好地理解线程正在做什么,但它不一定是更好的代码设计。
正如布莱恩所说,它会重置中断标志,但这并没有多说。在你的情况下它将什么都不做,View
- 线程将继续运行。
当中断线程时,标准过程是线程应该停止运行。它不会自动执行此操作,您必须实现一种方法,以便在中断后停止它。
使用内置功能有两个选项:
InterruptedException
的try-block中。这样,当它被中断时,你将被抛出循环,方法将退出。无论哪种方式,您都必须检查线程是否在while循环中被中断(在while循环中使用!Thread.currentThread().isInterrupted()
- 语句),或者它可能/不会退出。你没有完成第一个选项之一,也没有检查标志,所以你的View
- 线程将在被中断后继续运行。
答案 3 :(得分:0)
是否真的有必要在
Thread.currentThread().interrupt();
声明之前致电return;
?
作为一个观点,我总是这样做。我们所有的复制粘贴代码和吞下中断都是一个严重的问题,我通常总是这样做,即使线程即将死亡。
return;
是否已经执行了足够干净的退出?
如果您确定它是run()
方法完成并且线程退出之前的最后一次返回,那么是的,这在技术上是不必要的。但见上文。对于子孙后代,return;
对中断标志没有任何作用。
问题是您的View
课程是否已被包裹。您确定当您返回时退出Thread
。也许有人委托给它。 AOP可能会用来做某种仪器。
调用它有什么好处?文章指出应该这样做,因为否则“[...]更高的代码堆栈上的代码将无法找到它[...]”。
通常,当代码被某种需要中断标志的包装代码(委托,AOP等)调用时,不要吞下中断是很重要的。如果你吞咽它,包装器就无法使用它。但在这种情况下,没有任何好处。
Thread.State.TERMINATED中的一个线程有什么好处,在应用程序关闭时没有设置中断标志?
无。一旦线程退出中断状态就毫无价值。实际上,看起来在线程死后,中断状态甚至不会持续存在。
Thread thread = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
System.out.println("caught");
}
}
});
thread.start();
thread.interrupt();
System.out.println(thread.isInterrupted());
thread.join();
System.out.println(thread.isInterrupted());
打印:
true
caught
false
你能举个例子说明Runnable以外的代码是否有合理的原因检查中断的标志?
我不能。在线程的run()
方法之外没有代码,除非有人在你不知情的情况下将runnable包装在其他代码中。
如果您使用的是ExecutorService
,可能会发生这种情况,但在这种情况下,线程的中断状态会在作业运行之前用wt.isInterrupted()
明确清除。
再说一次,原因是因为它是一个很好的模式,而且在软件工程中是重要的。