首頁 > Java > java教程 > Java中關於守護線程和使用者線程的詳細介紹

Java中關於守護線程和使用者線程的詳細介紹

黄舟
發布: 2017-09-30 09:47:26
原創
1786 人瀏覽過

本篇文章主要介紹了淺談java中守護線程與用戶線程,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟著小編過來看看吧

Java線程分成兩類分別為daemon線程(守護線程)和User線程(用戶線程),在JVM啟動時候會呼叫main函數,main函數所在的線程是一個使用者線程,這個是我們可以看到的線程,其實JVM內部同時也啟動了很多守護線程,像是垃圾回收線程。那麼守護線程和使用者線程有什麼差別那?其中一個差異是當最後一個非守護線程結束時候,JVM會正常退出,而不管目前是否有守護線程,也就是說守護線程是否結束並不會影響JVM的退出。言下之意是只要有一個使用者執行緒還沒結束正常情況下JVM就不會退出。

那麼Java中如何建立一個守護線程那?程式碼如下:


public static void main(String[] args) {

    Thread daemonThread = new Thread(new Runnable() {
      public void run() {
        
      }
    });
    
    //设置为守护线程
    daemonThread.setDaemon(true);
    daemonThread.start();
    
  }
登入後複製

可知只需要設定執行緒的daemon參數為true。

下面透過範例來加深使用者執行緒與守護執行緒的差異的理解,首先看下面程式碼:


#
public static void main(String[] args) {

    Thread thread = new Thread(new Runnable() {
      public void run() {
        for(;;){}
      }
    });
    
    //启动子线
    thread.start();
    
    System.out.print("main thread is over");
  }
登入後複製

結果輸出為:


如上程式碼在main線程中創建了一個thread線程,thread線程裡面是無限循環,運行程式碼從結果看main線程已經運行結束了,那麼JVM進行已經退出了?從IDE的輸出結果右邊上的紅色方塊說明JVM程序並沒有退出,另外
mac上執行ps -eaf | grep java會輸出結果,也可以證明這個結論。

這個結果說明了當父執行緒結束後,子執行緒還是可以繼續存在的,也就是子執行緒的生命週期並不受父執行緒的影響。也說明了當用戶執行緒還存在的情況下JVM進程並不會終止。那我們把上面的thread執行緒​​設定為守護執行緒後在運行看看會有什麼效果:


    //设置为守护线程
    thread.setDaemon(true);
    //启动子线
    thread.start();
登入後複製

執行結果為:

#如上在啟動線程前設定線程為守護線程,從輸出結果可知JVM程序已經終止了,執行ps -eaf |grep java 也看不到JVM程序了。這個範例裡面main函數是唯一的使用者線程,thread線程是守護線程,當main線程運行結束後,JVM發現目前已經沒有使用者線程了,就會終止JVM程式。

Java中在main執行緒執行結束後,JVM會自動啟動一個叫做DestroyJavaVM線程,該執行緒會等待所有使用者執行緒結束後終止JVM進程,以下透過簡單的JVM程式碼來證明這個結論:

翻開JVM的程式碼,最後會呼叫到JavaMain這個c函數


int JNICALL
JavaMain(void * _args)
{  
  ...
  //执行Java中的main函数 
  (*env)->CallStaticVoidMethod(env, mainClass, mainID, mainArgs);
  
  //main函数返回值
  ret = (*env)->ExceptionOccurred(env) == NULL ? 0 : 1;
  
  //等待所有非守护线程结束,然后销毁JVM进程
  LEAVE();
}
登入後複製

LEAVE是c語言裡面的一個巨集定義,定義如下:


#define LEAVE() \
  do { \
    if ((*vm)->DetachCurrentThread(vm) != JNI_OK) { \
      JLI_ReportErrorMessage(JVM_ERROR2); \
      ret = 1; \
    } \
    if (JNI_TRUE) { \
      (*vm)->DestroyJavaVM(vm); \
      return ret; \
    } \
  } while (JNI_FALSE)
登入後複製

上面巨集的作用實際上是創建了一個名字叫做DestroyJavaVM的執行緒來等待所有使用者執行緒結束。

總結:如果你想在主線程結束後JVM進程馬上結束,那麼創建線程的時候可以設定線程為守護線程,否者如果希望主線程結束後子線程繼續工作,等子線程結束後在讓JVM進程結束那麼就設定子線程為用戶線程,開源框架Tomcat中就是用了守護線程和用戶線程聯合運行起來的,具體敬請期待Java並發編程基礎之並發包源碼剖析一書出版。

以上是Java中關於守護線程和使用者線程的詳細介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板