我们可以有虚假中断吗?

Fra*_*hey 3 java multithreading

我正在创建一个任务轮询器,它每分钟查找一次任务。它看起来像这样:

public class Poller {
    private final ExecutorService e = Executors.newSingleThreadExecutor();

    public void start() {
        e.submit(() -> {
            while (!Thread.currentThread().isInterrupted()) {
                final Task task = manager.getTask();

                if (task != null) {
                    // ...
                } else {
                    try {
                        TimeUnit.MINUTES.sleep(1);
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                    }
                }
            }
        });
    }

    public void stop() {
        e.shutdownNow();
    }
}
Run Code Online (Sandbox Code Playgroud)

当我想停止轮询进程时,我执行stop(). 这会触发正在运行的线程上的中断,这将停止轮询器。

这工作正常。但是,我想知道该线程是否有可能被其他人(很可能是 JVM)中断。在这种情况下,轮询器将退出而不应该退出。

我知道我们可能会有虚假的唤醒,所以我们必须wait()用 a来保护awhile (condition) { ... }而不是if (condition) { ... }。JVM 是否也会无缘无故地中断正在进行的线程?

在这种情况下,我应该引入 avolatile boolean并检查它而不是while (!Thread.currentThread().isInterrupted())?

Kay*_*man 5

是的,您应该引入一个volatile boolean来控制循环。不仅仅是因为可能出现虚假中断,还因为它使代码更具可读性。

您没有通过“保存” aboolean并使用线程的中断状态来控制循环来实现巧妙的优化,您使类的工作机制变得不那么明显。

编辑:我并没有真正回答核心问题(将其与唤醒混为一谈)。正如我们所知,虚假唤醒可以而且确实发生,这就是为什么我们使用保护子句/循环来检查条件是否真的得到满足。

虚假中断不是一回事,这意味着在 Java 生态系统中总是有一个线程在中断另一个线程(与唤醒不同,它的原因是外部的)。中断随机线程不是 Java 平台自己做的事情,但您可以编写一个线程,它只是随机选择其他线程并尝试中断它们。但是,这不是虚假中断,而是恶意中断。

  • 我理解这一点并且我同意这一点,但主要的问题是:可能会发生“虚假中断”? (2认同)
  • 好吧,您熟悉的虚假唤醒,正如您所知,其原因完全在 Java 平台之外。我从来没有听说过“虚假中断”,并且没有任何迹象表明 `InterruptedException` 可能是由除另一个线程中断该线程之外的任何其他线程引起的。在正常系统中,我真的看不到线程随机中断其他线程。也许在特殊情况下,例如在调试器下运行时,但即便如此,这也只是猜测。我看看能不能找到更多的信息。 (2认同)