首页 文章

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

提问于
浏览
30

我在教自己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 回答

  • 7

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

    Thread t = new Thread(...);
    t.setDaemon(true);
    

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

  • 11

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

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

  • 28

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

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

  • 11

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

    来自Javadoc of Thread

    当Java虚拟机启动时,通常会有一个非守护程序线程(通常调用某个指定类的名为main的方法) . Java虚拟机继续执行线程,直到发生以下任一情况:已调用类Runtime的exit方法,并且安全管理器已允许执行退出操作 . 所有非守护程序线程的线程都已死亡,无论是通过从run方法调用返回还是抛出传播超出run方法的异常 .

    如果您希望JVM终止,即使线程 t 正在运行,您应该make thread t a daemon thread

    t.setDaemon(true);
    
  • 0

    Java Language Specification section 12.8表示:

    12.8 . 程序退出程序终止其所有活动,并在发生以下两种情况之一时退出:所有不是守护程序线程的线程终止 . 某些线程调用类Runtime或类System的exit方法,安全管理器不禁止退出操作 .

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

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

  • 28

    主线程也是正在创建的用户线程,其生命周期类似于任何其他用户线程 .
    除非您将线程设置为守护程序线程,否则其他用户线程不会出于任何原因依赖于主线程 . 一旦主线程完成其工作,它就会结束(它既不会结束其他用户线程也不会结束进程,因为其他用户线程正在运行) .

相关问题