java - 如果我们不使用 join(),为什么多线程 C++ 程序会崩溃,而类似的 Java 程序不会
问题描述
假设我们有以下 C++ 程序
void hello (){
std :: cout << "HELLO"<<std::endl ;
}
int main(){
std:: thread t(hello) ;
t.join() ;
}
如果我们不在这段代码中调用 join,我们的程序将会崩溃,因为主线程会在线程 t1 完成之前终止。但是如果我们在 Java 中有相同的程序,即使 main 不等待线程,程序也会正常执行。
public class HelloWorld {
public static void main(String[] args) {
Thread t = new Thread(new Hello());
t.start();
}
}
class Hello implements Runnable {
public void run() {
System.out.println("Hello") ;
}
}
那么为什么在 Java 中程序不会崩溃呢?即使主线程先完成,线程如何执行?
解决方案
这相当简单:与 C++ 相比,它main
在完成后终止,Java 程序只有在所有(非守护程序)线程(包括主线程)都完成时才结束(例如,参见这个oracle 线程文档):
当 Java 虚拟机启动时,通常有一个非守护线程(通常调用某个指定类的名为 main 的方法)。Java 虚拟机继续执行线程,直到发生以下任一情况:
一种。已调用 Runtime 类的退出方法,并且安全管理器已允许进行退出操作。
湾。所有不是守护线程的线程都已经死亡,要么通过调用 run 方法返回,要么抛出传播到 run 方法之外的异常。
相比之下,C++ 将开始破坏具有静态存储持续时间的对象,如果分离的线程仍在运行并访问这些对象,则会产生未定义的行为(例如,参见有关程序终止的C++ 标准草案):
3.6.3 终止
作为从 main 返回的结果和调用 std::退出([support.start.term])。