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

时间:2012-12-16 19:27:54

标签: 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.");
}

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

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

6 个答案:

答案 0 :(得分:29)

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

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

答案 1 :(得分:28)

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

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

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

答案 2 :(得分:11)

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

来自Javadoc of Thread

  

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

     
      
  1. 已调用类Runtime的exit方法和安全性   经理允许退出操作。

  2.   
  3. 所有非守护程序线程的线程都已通过返回而死亡   从调用run方法或抛出异常   传播超出了run方法。

  4.   

如果您希望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)

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