在以下代码中:
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()线程。
发布于 2015-05-04 19:11:10
我不知道VM如何知道最后一个非守护进程线程何时停止运行的确切细节,但我可以想象两种解决方案:
后退出虚拟机
在这两种情况下,竞争条件是可能的,守护程序线程有时有时间在主线程死后再执行几个操作,有时不会。
我执行了几次您的代码,有时会在主线程退出后打印一些内容,有时不会,这证实了我的理论。
当我在t.join()之后添加一个Thread.sleep(100L)调用时,除了"Exit from main method“之外什么也没有打印出来。
还要注意,如果您查看VM中运行的线程列表(例如使用调试器),其中一个线程的名称为"DestroyJavaVM“。给定名称,我猜测这是在最后一个非守护线程停止运行后退出JVM的线程,并与其余的守护线程并发。
发布于 2015-05-04 19:24:59
你如何运行你的代码?
当我从命令行运行你的例子时,我得到: Exit from main method 1 |work|
我猜您可能不会打印出activeCount和|work|,因为当所有非守护进程线程都终止时(这里唯一的一个是main线程),JVM只能停止守护进程线程。当满足该条件时,JVM终止剩余的守护进程线程并退出。
Thread javadoc says:
Java虚拟机将继续执行线程,直到发生以下任一情况:
不过,终止这些线程可能需要一些时间,因此您的守护程序线程可能有机会执行更多指令。当我在打印activeCount之后添加Thread.sleep(1000)时,activeCount仍然被打印,但|work|不被打印。
发布于 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将证明作为非守护进程的主线程已经终止,因此不存在联接工作的问题...太迟了..。
https://stackoverflow.com/questions/30028428
复制相似问题