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等方法.

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