为什么一个线程比Java中的main方法更长?

Joh*_*0te 32 java multithreading

我在教自己Java线程,我注意到一些让我困惑的东西.我做了一个叫做engine实现的课Runnable.run方法只打印"Hello World",睡眠一秒,然后重复.

在我的主要方法中,我有:

public static void main(String[] args) {
    Thread thread = new Thread(engine);
    thread.start();
    System.out.println("Done.");
}
Run Code Online (Sandbox Code Playgroud)

正如我所料,我看到"Hello World"和"Done".快速打印,意味着主要方法已经到了最后,但我没想到的是,即使在主要结束之后,我开始运行的线程仍在运行.

为什么程序在主要退出后仍继续执行?我会想到,当主要退出时,进程将终止并且所有线程都将被强制清除.这是否意味着必须为每个Java程序显式连接/终止每个线程?

JB *_*zet 30

因为这是它的工作原理.程序在System.exit()调用时退出,或者在最后一个非守护程序线程停止运行时退出.

这是有道理的.例如,如果没有这个规则,每个只生成GUI的Java程序都必须无限地等待()以避免程序立即退出.


Zhe*_*dar 28

如果希望程序在main方法完成时退出,请考虑制作线程守护进程.但是要注意这样一个事实,当主要完成时,守护程序线程将被中止.
您可以像这样创建一个守护进程:

Thread t = new Thread(...);
t.setDaemon(true);
Run Code Online (Sandbox Code Playgroud)

所有非守护程序线程都是用户线程.那些线程正在阻止jvm关闭.

  • "当主要退出时,守护程序线程将被中止".只有当*all*创建的线程都是守护进程时才是真的.规则是一旦唯一运行的线程是守护程序线程,JVM就会退出,但守护进程肯定会比主要线程更长. (4认同)

rep*_*mer 12

用户线程继续独立于其父线程的生命周期运行,即创建者线程.因此,您必须通过Thread.joinmain线程终止之前调用来显式连接线程.

来自JavadocThread:

当Java虚拟机启动时,通常会有一个非守护程序线程(通常调用某个指定类的名为main的方法).Java虚拟机继续执行线程,直到发生以下任一情况:

  1. 已调用类Runtime的exit方法,并且安全管理器已允许执行退出操作.

  2. 所有非守护程序线程的线程都已死亡,无论是通过从run方法调用返回还是抛出传播超出run方法的异常.

如果您希望JVM即使线程t正在运行也要终止,那么您应该将线程t作为守护程序线程:

t.setDaemon(true);
Run Code Online (Sandbox Code Playgroud)


NPE*_*NPE 11

有两种类型的线程,用户和守护进程.当没有更多用户线程时,该进程终止.主线程始终是用户线程.您启动的线程也是一个用户线程,因此只要它运行就会使进程保持活动状态.

setDaemon(true)在启动它之前调用您的线程将使您的进程在main()函数返回后立即终止(或多或少).


Avi*_*gal 7

Java语言规范部分12.8表明:

12.8.程序退出

程序会终止其所有活动,并在发生以下两种情况之一时退出:

所有不是守护程序线程的线程都会终止.

某些线程调用类Runtime或类System的exit方法,安全管理器不禁止退出操作.

这意味着主线程完成是不够的.

如果你希望它在主线程结束时退出,你需要使用Thread#setDaemon使新线程成为守护进程,或者按照你最初的建议使用Thread#join.