我正在创建一个每分钟查找任务的任务轮询器。它看起来像这样:
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())
?
答案 0 :(得分:2)
是的,您应该引入volatile boolean
来控制循环。不仅因为可能存在虚假中断,还因为它使代码更具可读性。
你没有通过“保存”boolean
并使用线程的中断状态来控制循环来实现聪明的优化,你对这个类的工作机制不太明显是
编辑:我并没有真正回答核心问题(混淆了唤醒)。我们知道,spurious wakeups可以而且确实发生了,这就是为什么我们使用保护子句/循环来检查条件是否真的满足。
虚假中断不是一件事,这意味着总是有一个线程在Java生态系统内部中断另一个线程(与唤醒不同,其原因是外部的)。中断随机线程不是Java平台本身所做的事情,但是您可以编写一个线程,只是随机选择其他线程并尝试中断它们。然而,这不会是一个虚假的中断,那将是恶意中断。