【问题标题】:WHY does Thread.sleep() clear the interrupted flag? [duplicate]为什么 Thread.sleep() 清除中断标志? [复制]
【发布时间】:2014-07-18 18:32:52
【问题描述】:

我知道某些线程方法会清除中断标志(例如睡眠、等待……)。 但他们为什么这样做呢?这是什么原因?

【问题讨论】:

  • @Zoyd:这个问题没有完全解决为什么

标签: java multithreading sleep


【解决方案1】:

这是将中断设计为完全等同于取消的结果。 Oracle 的指导是仅将中断用于取消,但这种观点可能随着时间的推移而出现。无论如何,设计并不强制这样做。你可以设计一个任务来响应中断,然后回到它正在做的事情。

在 Java Concurrency in Practice, 7.1, page 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();
    }
}

(很多代码都是这样做的,因为程序员已经在他们的脑海中敲过,他们甚至不应该考虑使用异常来进行流控制),那么你必须设置中断标志。

我认为意图是应用程序开发人员应该使用异常来逃避中断的上下文,在靠近源头的地方吃异常并不能干净地工作。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 这可能是最好的答案,但值得详细说明线程状态、阻塞 IO、异常和标志在这件事中的关系。
    猜你喜欢
    • 2021-12-09
    • 2018-10-07
    • 2018-03-06
    • 1970-01-01
    • 2016-12-04
    • 1970-01-01
    • 2019-11-03
    • 1970-01-01
    • 2021-03-19
    相关资源
    最近更新 更多