java - JVM 在守护线程未完成之前不退出

标签 java multithreading

我刚刚偶然发现守护线程的一种奇怪行为,我无法解释。我已将我的代码缩减为最小、完整且可验证的示例:

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/

相关文章:

java - ThreadLocal.java中0x61C88647常量的含义是什么

c# - 如何使用 parallel.for 将项目添加到列表

multithreading - 这个字数 bolt 线程如何安全?

c# - .Net 4.0 中的并行功能

Java - OpenGL 设置中心 (0,0) 坐标的偏移量

Java:确定静态方法是从实例调用还是静态调用

multithreading - threadvar 和局部变量有什么区别

c++ - 线程池的 lambda 函数内部的编译器错误变量 "Not captured"

java - 堆排序实现bug,与插入函数

java - Java中什么时候应该使用float类型?