我对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之类的事情。我想念什么?
最佳答案
否。中断线程会设置一个标志,下次调用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();
}
我发现在外面做起来更清楚,因为它清楚地表明中断会停止循环迭代。