首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么当main()线程执行结束时,连接到main()线程的守护进程线程不会死?

为什么当main()线程执行结束时,连接到main()线程的守护进程线程不会死?
EN

Stack Overflow用户
提问于 2015-05-04 18:59:19
回答 3查看 780关注 0票数 3

在以下代码中:

代码语言:javascript
复制
class Worker extends Thread {
    Thread t;

    public Worker(Thread thread) {
        t=thread;
    }

    public void run() {
        try {
            t.join();
        } catch(InterruptedException e) {
            System.out.println("Exception is thrown and caught");
        }
        System.out.println(Thread.activeCount());
        System.out.print("|work|");
    }

    public static void main(String[] args) {
        Thread t=Thread.currentThread();
        Worker worker = new Worker(t);
        worker.setDaemon(true);
        worker.start();
        System.out.println("Exit from main method");
    }
}

由于worker是在main()线程上联接的守护程序线程,因此不应该打印|work|,因为用户线程main()首先完成,而且由于worker是守护程序线程,所以当main()线程终止时,它也会停止。但是,我得到的输出如下: Exit from main method 1 |work|

请为我澄清这个问题。

在多次执行该程序之后,我观察到以下不同的输出:

不使用Thread.sleep(1000):

退出主方法2

退出主方法1|工作|

退出主要方法2|工作|

使用Thread.sleep(1000):

退出主要方法2|工作|

退出main方法

注意第一个不带sleep()方法的输出。|work|未打印,但线程数显示为2。这是否意味着主()线程在Thread.activeCount()之后但|work|打印之前结束?在第三个输出中,main()似乎在执行完这两个语句后结束。

现在,我从来没有想过Thread.activeCount()会是2,因为守护线程工作线程是在用户线程main()上联接的,这意味着当执行Thread.activeCount()时,将只有工作线程而没有main()线程。

EN

回答 3

Stack Overflow用户

发布于 2015-05-04 19:11:10

我不知道VM如何知道最后一个非守护进程线程何时停止运行的确切细节,但我可以想象两种解决方案:

  • a background定期轮询以查看是否所有非守护程序线程都已退出(我怀疑这是否是实际解决方案)
  • 后台线程在所有非守护程序线程上加入,并在所有加入返回

后退出虚拟机

在这两种情况下,竞争条件是可能的,守护程序线程有时有时间在主线程死后再执行几个操作,有时不会。

我执行了几次您的代码,有时会在主线程退出后打印一些内容,有时不会,这证实了我的理论。

当我在t.join()之后添加一个Thread.sleep(100L)调用时,除了"Exit from main method“之外什么也没有打印出来。

还要注意,如果您查看VM中运行的线程列表(例如使用调试器),其中一个线程的名称为"DestroyJavaVM“。给定名称,我猜测这是在最后一个非守护线程停止运行后退出JVM的线程,并与其余的守护线程并发。

票数 2
EN

Stack Overflow用户

发布于 2015-05-04 19:24:59

你如何运行你的代码?

当我从命令行运行你的例子时,我得到: Exit from main method 1 |work|

我猜您可能不会打印出activeCount|work|,因为当所有非守护进程线程都终止时(这里唯一的一个是main线程),JVM只能停止守护进程线程。当满足该条件时,JVM终止剩余的守护进程线程并退出。

Thread javadoc says:

Java虚拟机将继续执行线程,直到发生以下任一情况:

  • 类Runtime的exit方法已被调用,并且安全管理器已允许执行exit操作。
  • 通过从对run方法的调用返回或引发传播到run方法之外的异常,所有非守护程序线程都已死亡。

不过,终止这些线程可能需要一些时间,因此您的守护程序线程可能有机会执行更多指令。当我在打印activeCount之后添加Thread.sleep(1000)时,activeCount仍然被打印,但|work|不被打印。

票数 0
EN

Stack Overflow用户

发布于 2015-05-05 19:28:19

让我首先尝试回答以下输出

不使用Thread.sleep(1000)

退出主方法2-你必须记住你的工作线程是一个守护进程,所以JVM不会等待它完成它的执行。它只为完成主线程的执行而烦恼,它是一个非守护进程。现在您会得到这个输出,因为主线程显示了"Exit from Main Method“,同时工作线程运行并显示了2,但不幸的是,主线程完成了,JVM没有等待工作线程(作为守护进程),因此没有显示”work“。

退出主方法1 |work| -这里使用与上面相同的解释,工作线程很幸运,在..it完成主线程并匆忙退出之前,它有足够的时间显示'|work|‘。

退出main method 2 |work| -与之前的explanation...not相同确定为什么active count有时返回2,有时返回1。

您可以使用类似的逻辑得出以下结论

使用Thread.sleep(1000)逻辑。

提示:您还可以使用语句System.out.println("status of t:“+t.getState())检查线程t的状态;就在t.join()....you将被终止之前,lot..which将证明作为非守护进程的主线程已经终止,因此不存在联接工作的问题...太迟了..。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30028428

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档