为什么Thread.sleep()清除中断的标志?

时间:2014-05-29 09:35:50

标签: java multithreading sleep

我知道有些Thread方法会清除中断的标志(例如睡眠,等待......)。 但为什么他们这样做?它是什么原因?

2 个答案:

答案 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)

简而言之,因为这些方法将线程发送到“新鲜”等待状态(在它被中断回到运行状态之后)。先前设置的“中断”标志不再适用,因为线程自进入新的等待状态后未被中断。