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

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();
    }
}

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

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

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

在这种情况下,我应该介绍一个volatile boolean并检查它,而不是while (!Thread.currentThread().isInterrupted())

最佳答案

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

您无法通过“保存” boolean并使用线程的中断状态来控制循环来实现聪明的优化,但是对于类的工作机制却不那么清楚。

编辑:我并没有真正回答核心问题(将其与唤醒功能混在一起)。众所周知,spurious wakeups可以并且确实会发生,这就是为什么我们使用保护子句/循环来检查条件是否真正满足的原因。

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

09-27 17:17