我在教自己Java线程,我注意到一些让我困惑的东西 . 我创建了一个名为 engine
的类,实现 Runnable
. run方法只打印"Hello World",睡眠一秒钟,然后重复 .
在我的主要方法中,我有:
public static void main(String[] args) {
Thread thread = new Thread(engine);
thread.start();
System.out.println("Done.");
}
正如我所料,我看到“Hello World”和“Done” . 快速打印,意味着主要方法已经到了最后,但我没想到的是,即使在主要结束之后,我开始运行的线程仍在运行 .
为什么程序在主要退出后仍继续执行?我会想到,当主要退出时,进程将终止并且所有线程都将被强制清除 . 这是否意味着必须为每个Java程序显式连接/终止每个线程?
6 回答
如果希望程序在main方法完成时退出,请考虑制作线程守护进程 . 但是要注意这样一个事实,当主要完成时,守护程序线程将被中止 .
您可以像这样创建一个守护进程:
所有非守护程序线程都是用户线程 . 那些线程正在阻止jvm关闭 .
因为这是它的工作原理 . 调用
System.exit()
时,或最后一个非守护程序线程停止运行时,程序退出 .这是有道理的 . 例如,如果没有这个规则,每个只生成GUI的Java程序都必须无限地等待()以避免程序立即退出 .
有两种类型的线程,用户和守护进程 . 当没有更多用户线程时,该进程终止 . 主线程始终是用户线程 . 您启动的线程也是一个用户线程,因此只要它运行就会使进程保持活动状态 .
在启动它之前在线程上调用setDaemon(true)将使您的进程在
main()
函数返回后立即终止(或多或少) .用户线程继续独立于其父线程的生命周期运行,即创建者线程 . 因此,您必须通过在
main
线程终止之前调用Thread.join来显式连接线程 .来自Javadoc of Thread:
如果您希望JVM终止,即使线程
t
正在运行,您应该make thread t a daemon thread:Java Language Specification section 12.8表示:
这意味着主线程完成是不够的 .
如果你确实希望它在主线程结束时退出,你需要使用Thread#setDaemon使新线程成为守护进程,或者按照最初的建议使用Thread#join .
主线程也是正在创建的用户线程,其生命周期类似于任何其他用户线程 .
除非您将线程设置为守护程序线程,否则其他用户线程不会出于任何原因依赖于主线程 . 一旦主线程完成其工作,它就会结束(它既不会结束其他用户线程也不会结束进程,因为其他用户线程正在运行) .