我在教自己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程序显式连接/终止每个线程?
答案 0 :(得分:29)
因为它是如何运作的。调用System.exit()
时,或者最后一个非守护程序线程停止运行时,程序退出。
这是有道理的。例如,如果没有这个规则,每个只生成GUI的Java程序都必须无限地等待()以避免程序立即退出。
答案 1 :(得分:28)
如果希望程序在main方法完成时退出,请考虑制作线程守护进程。但是要注意这样一个事实,当主要完成时,守护程序线程将被中止 您可以像这样创建一个守护进程:
Thread t = new Thread(...);
t.setDaemon(true);
所有非守护程序线程都是用户线程。那些线程正在阻止jvm关闭。
答案 2 :(得分:11)
用户线程继续独立于其父线程的生命周期运行,即创建者线程。因此,您必须通过在main
线程终止之前调用Thread.join
来显式加入线程。
当Java虚拟机启动时,通常只有一个 非守护程序线程(通常调用名为main的方法) 指定班级)。 Java虚拟机继续执行 线程,直到发生以下任一情况:
已调用类Runtime的exit方法和安全性 经理允许退出操作。
- 醇>
所有非守护程序线程的线程都已通过返回而死亡 从调用run方法或抛出异常 传播超出了run方法。
如果您希望JVM在线程t
正在运行时终止,您应该make thread t
a daemon thread:
t.setDaemon(true);
答案 3 :(得分:11)
有两种类型的线程,用户和守护进程。当没有更多用户线程时,该进程终止。主线程始终是用户线程。您启动的线程也是一个用户线程,因此只要它运行就会使进程保持活动状态。
在启动它之前在您的线程上调用setDaemon(true)
将使您的main()
函数返回后立即终止(或多或少)。
答案 4 :(得分:7)
Java Language Specification section 12.8表示:
12.8。程序退出
程序终止其所有活动,并在两件事之一时退出 发生的情况:
所有不是守护程序线程的线程都会终止。
某些线程调用Runtime类或类System的exit方法, 并且安全管理员不禁止退出操作。
这意味着主线程完成是不够的。
如果你确实希望它在主线程结束时退出,你需要使用Thread#setDaemon或者按照你最初的建议使用Thread#join使新线程成为守护进程。
答案 5 :(得分:0)
主线程也是正在创建的用户线程,其生命周期类似于任何其他用户线程。
除非您将线程设置为守护程序线程,否则其他用户线程不会出于任何原因依赖于主线程。
一旦主线程完成其工作,它就会结束(它既不会结束其他用户线程也不会结束进程,因为其他用户线程正在运行)。