JVM退出后守护线程如何存活?

How does daemon thread survive after JVM exits?

我正在阅读有关 Java 的 setDaemon() 方法的文档,当我读到 JVM 不等待守护线程完成就退出时感到困惑。

然而,由于守护线程本质上是 Java Thread 的,这大概依赖于 运行 JVM 来实现其功能,如果 JVM 退出,守护线程如何生存在守护线程完成之前?

他们无法生存。当所有线程(守护程序线程除外)都已死亡时,JVM 将退出。

当您启动您的应用程序时,JVM 将启动一个单一的非守护线程到 运行 您的静态 main 方法。

一旦 main 方法退出,这个主线程就会死掉,如果你没有生成其他非守护线程,JVM 就会退出。

但是,如果您启动了另一个线程,JVM 将不会退出,它会等待所有非守护线程结束后再退出。

如果您生成的那个线程正在做一些重要的事情,这绝对是正确的做法,但是通常您有一些线程并不那么重要,也许它们正在监听一些可能发生也可能不发生的外部事件.

因此,理论上,您应该在某处放置一些代码来停止您生成的所有线程,以允许 JVM 退出。

由于这很容易出错,因此将此类非重要线程标记为守护进程要容易得多。如果它们被标记为这样,JVM 将不会等待它们在退出前死亡,JVM 将在 "main threads"(未标记为守护进程的线程)死亡时退出并杀死这些线程。

写成代码是这样的:

public class Spawner {
  public static void main(String[] args) {
    Thread t = new Thread(new Runnable() {
      public void run() {
        while (true) {
          System.out.println("I'm still alive");
        }
      }
    });
    // Try uncommenting/commenting this line
    // t.setDaemon(true);
    t.start();
    System.out.println("Main thread has finished");
  }
}

(我没有测试过这段代码,直接写在这里,所以可能会有愚蠢的错误)。

当运行将此代码与注释行结合使用时,线程不是守护进程,因此即使您的主要方法已完成,您仍会继续淹没控制台,直到您使用 CTRL+ 停止它C。即JVM不会退出。

如果取消注释该行,则该线程是守护进程,main方法完成后不久,线程将被杀死,JVM将退出,不需要CTRL+C。