main线程终止,其他线程还会运行吗?

main线程终止,其他线程还会运行吗? 


01 理论分析

当你启动一个Java Application的时候,这个时候系统创建一个进程,分配各项资源,然后这个进程启动了Main线程.
我们一般把Main线程说成主线程,因为其他线程一般是由main线程启动的.但其实,在进程层面看起来,main其实也是一个普通的线程.只不过一些其他的线程都是由main启动的.
我们可以猜想一下:正常情况下,main线程启动了其他线程,他们各自执行,彼此不受影响.
猜想依据:因为操作系统分配资源的单位是进程,就算main线程退出了,进程也还在.资源还在.在进程看来,线程应该都是平级的,没有父子关系.
这个问题也可以换个说法,main线程是最后退出的线程吗?

02 实践验证

我们模拟一个线程池的例子,从main线程启动一个线程池,当发生异常,则让main线程抛出异常终止,看看线程池是否还继续运行.
这里由于网上有些争论认为打印的方式无法判断main线程是否终止,所以我们的示例使用异常终止,并且使用jconsole工具进行验证.

public class ThreadPoolException {     
       ExecutorService threadPool = Executors.newFixedThreadPool(5);     
       public static void main(String[] args) {         
              ThreadPoolException t = new ThreadPoolException();         
              t.futureGet();     
       }      
       void futureGet() {         
              for (int i = 0; i < 5; i++) {             
                   Future future = threadPool.submit(() -> {                 
                          System.out.println("current thread name" + Thread.currentThread().getName());                 
                          Object object = null;                 
                          System.out.print("result## " + object.toString());             
                   });             
                   try {                 
                          future.get();             
                   } catch (Exception e) {                 
                           System.out.println(Thread.currentThread().getName() + "异常");                 
                           // 让主线程多等一段时间,便于观察. 
                           try {                     
                                Thread.sleep(10000);                 
                           } catch (InterruptedException e1) {                     
                                e1.printStackTrace();                 
                           }                 
                           //主线程终止 
                           throw new RuntimeException(Thread.currentThread().getName() + "异常");             
                }         
        }     
     } 
}		  
欢迎大家关注我,需要更多Java面试资料和学习干货可以关注我的专栏【Tom猫的Java屋

Tom猫的java屋​zhuanlan.zhihu.com图标

我们可以在jconsole中观察到:


在main线程先出现然后会消失,线程池中的线程还在,只不过是wait状态. 在idea中直接运行代码,也可以观察到同样的结论.


03 总结

  • JVM会在所有的非守护线程(用户线程)执行完毕后退出;
  • main线程是用户线程;
  • 仅有main线程一个用户线程执行完毕,不能决定JVM是否退出,也即是说main线程并不一定是最后一个退出的线程。

如果你希望在main线程退出后,所有其他线程也退出.那么你可以把其他线程都设置为守护线程,也就是setDaemon(true). 对于线程池,你可以在main线程退出的的时候手动进行一些处理.比如shutdown等方法.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章