我知道有些Thread方法会清除中断的标志(例如睡眠,等待......)。 但为什么他们这样做?它是什么原因?
答案 0 :(得分:6)
这是因为中断设计不与取消完全同义。 Oracle的指导是仅将中断用于取消,但该视图可能已经过时。无论如何,设计并没有强制这样做。您可以设计一个任务来响应中断,然后再回到它正在做的事情。
在Java Concurrency in Practice,7.1,第138页中,它说:
API或语言规范中没有任何内容将中断与任何特定的取消语义联系起来,但在实践中,使用中断除了取消之外的任何事情都是脆弱的,并且在大型应用程序中可以维持。
它的设计方式在任何给定时间都有一件事,要么是被捕获的InterruptedException,要么是中断标志,以告诉线程的状态。如果InterruptedException正在进行中,则该标志的值无关紧要。并且想法似乎是捕获异常的代码应该决定是否应该设置中断标志。
这样可以方便地使用InterruptedException退出循环:
try {
while (!Thread.currentThread().isInterrupted()) {
Thread.sleep(5000);
// ... do stuff ...
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
这里线程停止循环,因为异常被捕获到循环之外,只有中断标志被置位才对任何周围的代码都有意义。但是,如果在循环中捕获InterruptedException,例如:
while (!Thread.currentThread().isInterrupted()) {
// ... do stuff ...
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
(并且很多代码都是这样做的,因为程序员已经把它们砸到脑子里,他们甚至不应该考虑使用流控制的异常),然后你必须设置中断的标志。
我认为目的是应用程序开发人员应该使用异常来逃避中断的上下文,吃掉接近源的异常并不能正常工作。
答案 1 :(得分:2)
简而言之,因为这些方法将线程发送到“新鲜”等待状态(在它被中断回到运行状态之后)。先前设置的“中断”标志不再适用,因为线程自进入新的等待状态后未被中断。