我正在创建一个任务轮询器,每分钟查找一次任务。看起来像这样:
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平台本身要做的事情,但是您可以编写一个线程,该线程只是随机选择其他线程并尝试中断它们。但是,这不是虚假的中断,而是恶意的中断。