【问题标题】:will main thread exit before child threads complete execution? [duplicate]主线程会在子线程完成执行之前退出吗? [复制]
【发布时间】:2021-03-04 05:48:32
【问题描述】:

主线程会在子线程完成执行之前退出吗?

我读了两篇文章

http://www.cs.mtu.edu/~shene/NSF-3/e-Book/FUNDAMENTALS/thread-management.html

在上面的文章中,在“线程终止”段落中,它以红色表示“如果父线程终止,则其所有子线程也终止。”

http://www.roseindia.net/java/thread/overview-of-thread.shtml

在上面的文章中,该页面的最后一行声明“main() 方法执行可以完成,但程序将继续运行,直到所有线程都完成执行。”。

我觉得它们是矛盾的。如果我错了,请专家纠正我。

在我的程序中,一个带有 Main 方法的程序调用了 2 个线程的构造函数。在各个线程的构造函数中,我有 start() 方法。

     TestA  A = new TestA("TestA");
     TestB  B = new TestB("TestB");

     public TestA(String name) {
    System.out.println(name);
    t = new Thread(this);
    t.start();
}

我想知道发生了什么,主线程在子线程完成执行之前终止?如果是这样,子线程是否会继续执行?

我尝试运行程序,有时即使主线程退出,所有子线程也会执行完成。 在 2 个线程中,我正在处理一些文件。在单独的 testA 线程 A 中,单独的 1 个文件有时不会被处理。但很多时候,所有文件都得到处理,我没有任何问题。

【问题讨论】:

  • 下面的答案很好,但他们没有解释为什么在链接的文章中写了if the parent thread terminates, all of its child threads terminate as well.。实际上在 C/C++ 中与 Java 不同,当主线程终止时,进程终止,所有其他线程停止。

标签: java


【解决方案1】:

Java 对用户线程和另一种称为守护线程的线程进行了区分。这两种线程的区别在于,如果 JVM 确定应用程序中运行的唯一线程是守护线程(即没有用户线程),则 Java 运行时会关闭应用程序。另一方面,如果至少有一个用户线程处于活动状态,Java 运行时不会终止您的应用程序。

当您的 main() 方法最初从 Java 运行时接收控制时,它会在用户线程的上下文中执行。只要主方法线程或任何其他用户线程保持活动状态,您的应用程序就会继续执行。

在您的情况下,线程是用户线程,因此可以在主线程退出之前完成。

我正在处理一些文件。在testA线程A单独,1个文件单独是 有时没有得到处理。但是很多次

上述原因可能不是线程退出。可能是文件锁定、同步问题等。

Thread (Java SE 10 & JDK 10):

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

  • Runtime 类的 exit 方法已被调用,安全管理器已允许执行退出操作。
  • 不是守护线程的所有线程都已死亡,要么从对 run 方法的调用返回,要么抛出传播到 run 方法之外的异常。

【讨论】:

  • 感谢您的详细解释。您已经提到“在您的情况下,线程是用户线程,因此可以在主线程退出之前完成。”在这里,您的意思是“主线程”是 Java 运行时,而不是带有 main method() 的程序。对吗?
  • 具有main方法的类和在main方法中创建的线程都是用户线程。所有这些线程都是独立的并发执行。因为我给了 System.out.println("exit of main method");在 main 方法的末尾。这在子线程中的 system.out.println() 之前打印。这让我认为主线程(具有 main 方法的类)甚至可以在子线程之前退出。这是正确的行为方式吗?
  • 你能澄清一下文件锁是什么意思吗?在此先感谢!
  • “这里你的意思是“主线程”是 Java 运行时而不是带有 main method() 的程序。对吗?”。是的。 “这在子线程中的 system.out.println() 之前打印。这让我认为主线程(具有 main 方法的类)甚至可以在子线程之前退出。这是正确的行为方式吗? "虽然主线程完成,但 JVM 不会关闭,直到应用程序中仍有非守护线程在执行。
  • "你能澄清一下文件锁是什么意思吗?"当一个进程/线程正在访问一个文件时,它会获得对该文件的锁定,当另一个进程/线程试图访问同一个文件时,它会导致错误。
【解决方案2】:

即使主线程完成,后台线程也会继续运行。

如果您希望 MAIN 停止它们(例如,当 MAIN 完成时),请让您的 MAIN 设置一个“继续运行”标志变量(您必须将其设置为“volatile”),线程偶尔会查看它。当 MAIN 想要停止它们时,MAIN 将其设置为 false(变量)或 null(对象)。当它为 false 或 null 时,线程必须“return;”。

这实现起来有点复杂,有很多方法,但最简单的方法是让你的 Runnable 成为一个内部类,这样你的 Runnable 就可以轻松共享标志。

要获得最佳实现,请在 Java 小程序的启动/停止例程中查找此技术。

【讨论】:

  • 首先在实际中,通过flag控制是不明智的,尤其是在main方法中。您可以通过使用守护线程来实现它
【解决方案3】:

一旦主线程退出,它就会带走子线程。也许“完成”第二条只是意味着除了等待孩子之外没有更多的操作。一旦主线程调用 System.exit(0);结束了——每个人都死了。

假设你有两个线程在运行:threadA 和 threadB。在主要方法中。第一个代码是终止线程的好方法——只是众多方法中的一种:

 threadA.start();
 threadB.start();
 final long intercept = 300;
 long startTime = System.currentTimeMillis();
 while (threadA.isAlive() && mis.isAlive()) {
    threadA.join(intercept);
if (System.currentTimeMillis() - startTime > intercept) {
   threadB.interrupt();
   threadA.interrupt();
   threadA.join();
}
}
System.exit(0);

下面是从 main 中杀死所有线程的突然方法:

System.exit(0);

【讨论】:

  • 感谢您的回复。我从未在我的程序中使用过 System.exit(0)。“一旦主线程退出,它就会带着孩子们”。我仍然不清楚。具有 main 方法的程序创建 2 个线程并完成。但是产生的子线程会继续,这不正确吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多