我对Java教程中的以下示例有疑问:https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
for (int i = 0; i < importantInfo.length; i++) {
// Pause for 4 seconds
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
// We've been interrupted: no more messages.
return;
}
// Print a message
System.out.println(importantInfo[i]);
}
Java教程似乎建议这样可以很好地处理异常,因为大部分执行时间将花在Thread.sleep()中,如果线程收到中断,则会抛出InterruptedException。
但是,如果在代码执行println
时收到中断,则此示例无法完全错过中断?因此,最安全的做法是修改它,如下所示(添加另一个调用Thread.interrupted())?
for (int i = 0; i < importantInfo.length; i++) {
// Pause for 4 seconds
try {
if (Thread.interrupted()){
throw new InterruptedException()
}
Thread.sleep(4000);
} catch (InterruptedException e) {
// We've been interrupted: no more messages.
return;
}
// Print a message
System.out.println(importantInfo[i]);
}
但实际上,如果是这样的话,我们永远不能依赖InterruptedException来提供帮助,除非我们有时会错过它,或者如果我们在一个循环或其他东西中断了Threads。我错过了什么?
答案 0 :(得分:6)
没有。中断线程会设置一个标志,下次调用Thread.sleep(...)
时会检查该标志。
因此,即使中断发生时它不在Thread.sleep
中,也不会丢失中断。
要做的一件重要事情是在捕获InterruptedException
时重新中断线程:
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
// ...
}
这允许此方法之外的代码知道此方法提前完成的原因是因为中断;它也应该处理中断。如果run()
方法直接由Thread
执行,则这可能无关紧要;但这不是运行该方法的唯一方法。
顺便说一下,编写该代码的一种更简洁的方法是捕获循环外的中断:
try {
for (int i = 0; i < importantInfo.length; i++) {
// Pause for 4 seconds
Thread.sleep(4000);
// Print a message
System.out.println(importantInfo[i]);
}
} catch (InterruptedException e) {
// We've been interrupted: no more messages.
Thread.currentThread().interrupt();
}
我发现外面这样做更清楚,因为它清楚地表明中断会停止循环迭代。