我刚刚偶然发现守护线程的一种奇怪行为,我无法解释。我已将我的代码缩减为最小、完整且可验证的示例:
public static void main(String[] args) throws InterruptedException {
Thread runner = new Thread(() -> {
final int SIZE = 350_000;
for (int i = 0; i < SIZE; i++) {
for (int j = i + 1; j < SIZE; j++) {
if (i*j == SIZE * SIZE - 1) {
return;
}
}
}
});
runner.setDaemon(true);
runner.start();
// Thread.sleep(1000);
System.out.println("Exiting.");
}
runner
线程执行的代码大约需要 12 秒才能在我的盒子上终止,我们对它的作用不感兴趣,因为我只需要花一些时间进行计算。
如果此代码段按原样运行,它将按预期工作:它在启动后立即终止。
如果我取消注释 Thread.sleep(1000)
行并运行该程序,它会运行大约 12 秒,然后打印出“Exiting”并终止。
据我了解守护线程是如何工作的,我希望这段代码运行 1 秒然后终止执行,因为唯一运行的用户线程是使用 main() 方法启动的线程(runner
是一个后台守护线程),一旦 1000 毫秒过去,它就会执行结束,JVM 应该停止。此外,“Exiting”仅在 12 秒后打印,而不是在程序启动时打印,这看起来很奇怪。
我错了吗?我怎样才能实现所需的行为(暂停一秒钟然后停止,独立于运行线程正在做什么)?
我在 Linux 机器上使用 64 位 Oracle JDK 1.8.0_112,无论是从 IDE 还是从命令行启动,它都具有相同的行为。
谢谢, 安德里亚
最佳答案
这可能是计数循环优化的结果,它从嵌套循环中删除了安全点轮询。尝试将 -XX:+UseCountedLoopSafepoint
标志添加到您的 JVM 启动选项。
关于java - JVM 在守护线程未完成之前不退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41445958/