【问题标题】:Is this appropriate use of Thread.interrupt()?这是对 Thread.interrupt() 的适当使用吗?
【发布时间】:2023-03-06 06:56:02
【问题描述】:

只要线程不中断,我希望一段代码运行。目前我正在做的是:

while(!Thread.interrupted()){
    // .. some code
    try {
        Thread.sleep(4000);
    } catch(InterruptedException ex){
        break;
    }
    // .. some more code
}

我的问题是:这是一种好的做法吗?使用interrupt是否合适?

【问题讨论】:

  • @AlexisLeclerc 目的似乎是“唤醒”线程而不是“杀死”它。
  • @CostiCiudatu 我不清楚这个问题。其实我确实想唤醒它,然后杀死它。
  • @CostiCiudatu 是的,我刚刚看到了。我链接的问题来自另一个标记为重复的问题,但似乎这个重复的问题有一个错误替换的链接。

标签: java multithreading


【解决方案1】:

是的,我认为这正是 interrupt() 的目的,所以这似乎是一种合法的用法。

【讨论】:

  • 嗯,是的,我希望线程从睡眠中出来并完成。那么在catch 中调用interruptreturning 以获取InterruptedException 是个好主意吗?
  • 我不这么认为。由于您实际上是在等待某个事件发生后再进行清理,因此这是Object.wait()Condition.await() 的标准用法。但是,如果您为您正在尝试做的事情提供更多上下文,它可能会很有用:为什么您希望您的线程在收到终止消息之前一直休眠?
  • @Prog 我现在意识到您每 4 秒执行一次该代码块,并且在中断时停止执行该操作。在这种情况下,我认为在这里使用interrupt 非常有意义。
  • 好的,确保我明白我在做什么:只要线程没有被告知停止,while 中的!Thread.interrupted() 就会使循环工作。并且在睡眠时使用catch(InterruptedException) 块来处理interrupt 是标准的。对吗?
  • 是的,唯一看起来有点令人困惑的是您是否关心最后执行的块(“一些代码”或“一些更多代码”);目前尚未确定。根据中断发生的位置(睡眠时或睡眠后),您可能会以第一个或第二个块作为最后执行的块结束。
【解决方案2】:

从概念上讲,这是在正确的轨道上。不过,有一些细节可以改进。

正确的是线程中断机制被用来告诉线程做其他事情,并且线程可以在它选择的时候以它喜欢的方式响应。在这种情况下,从Thread.sleep() 中捕获InterruptedException 并跳出循环是完全合理的做法。这当然比通常所做的要好得多,即完全忽略异常。 (这通常是错误的。)

可能的问题是循环条件检查线程是否已被中断。这可能是个问题,具体取决于 some codesome more code 正在做什么。根据检测到中断时执行了哪些代码块,您的系统可能会处于不同的状态。

除非循环的一次迭代运行很长时间(除了睡眠),否则通常只需要在循环中有一个中断点。在这种情况下,如果线程在执行some code 处理时被中断,则在调用Thread.sleep() 时将立即生成InterruptedException。因此,您可以将循环条件更改为 while (true) 并让 catch-block 跳出循环。 (如果您这样做,您还应该重新断言中断位;见下文。)

或者,如果您只想在循环顶部检查中断,您可以这样做:

while (!Thread.interrupted()) {
    // .. some code
    try {
        Thread.sleep(4000L);
    } catch (InterruptedException ie) {
        Thread.currentThread().interrupt();
    }
    // .. some more code
}

这使得循环中只有一个退出点,这可能使代码更容易推理。

注意这里使用的技术是在捕获InterruptedException重新断言线程上的中断位。处理中断的一般规则是要么重新声明中断位,要么传播InterruptedException。如果两者都没有完成,那么调用代码可能最终会在随后的wait() 调用中被阻塞,而不知道它曾经被中断过。这通常是一个错误。

【讨论】:

  • "...线程可以随心所欲地响应..." 我一直担心的一件事是,如果在我的线程处于库例程中时发生中断会发生什么。在这种情况下,库对象的状态将完全取决于库作者的喜好。我通常可以相信图书馆作者在中断后不会做任何比调用因其他原因失败而更糟糕的事情吗?我不记得曾经见过一个明确记录其中断处理行为的库。
  • @jameslarge 这取决于图书馆的质量,但是,是的,您的担心可能是对的。如果那里有库错误处理中断,我不会感到惊讶,主要是忽略它们。这导致人们认为“因此,我需要使用Thread.stop()”,这会导致一类全新的问题。参见例如this question
【解决方案3】:

好的做法是改用更新的更高级别的 API,例如 ExecutorService。您不应使用较低级别的 API,例如线程或 synchronizewait/notify

【讨论】:

    猜你喜欢
    • 2013-07-24
    • 1970-01-01
    • 1970-01-01
    • 2011-06-15
    • 1970-01-01
    • 1970-01-01
    • 2011-01-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多