java的守護線程與非守護線程

來源:互聯網
上載者:User


https://www.cnblogs.com/super-d2/p/3348183.html

最近重新研究Java基礎知識,發現以前太多知識知識略略帶過了,比較說Java的線程機制,在Java中有兩類線程:User Thread(使用者線程)、Daemon Thread(守護線程) ,(PS:以前忽略了)。

       估計學過Unix開發但是沒有細緻學習Java的同學們會疑惑了,作業系統裡面是沒有所謂的守護線程的概念,只有守護進程一說,但是Java語言機制是構建在JVM的基礎之上的,意思是Java平台把作業系統的底層給屏蔽起來,所以它可以在它自己的虛擬平台裡面構造出對自己有利的機制,而語言或者說平台的設計者多多少少是收到Unix思想的影響,而守護線程機制又是對JVM這樣的平台湊合,於是守護線程應運而生。

       Daemon的作用是為其他線程的運行提供服務,比如說GC線程。其實User Thread線程和Daemon Thread守護線程本質上來說去沒啥區別的,唯一的區別之處就在虛擬機器的離開:如果User Thread全部撤離,那麼Daemon Thread也就沒啥線程好服務的了,所以虛擬機器也就退出了。

       守護線程並非虛擬機器內部可以提供,使用者也可以自行的設定守護線程,方法:public final void setDaemon(boolean on) ;但是有幾點需要注意:

1)、thread.setDaemon(true)必須在thread.start()之前設定,否則會跑出一個IllegalThreadStateException異常。你不能把正在啟動並執行常規線程設定為守護線程。  (備忘:這點與守護進程有著明顯的區別,守護進程是建立後,讓進程擺脫原會話的控制+讓進程擺脫原進程組的控制+讓進程擺脫原控制終端的控制;所以說寄託於虛擬機器的語言機制跟系統級語言有著本質上面的區別)

2)、 在Daemon線程中產生的新線程也是Daemon的。  (這一點又是有著本質的區別了:守護進程fork()出來的子進程不再是守護進程,儘管它把父進程的進程相關資訊複製過去了,但是子進程的進程的父進程不是init進程,所謂的守護進程本質上說就是“父進程掛掉,init收養,然後檔案0,1,2都是/dev/null,目前的目錄到/”)

3)、不是所有的應用都可以分配給Daemon線程來進行服務,比如讀寫操作或者計算邏輯。因為在Daemon Thread還沒來的及進行操作時,虛擬機器可能已經退出了。

例子:

//完成檔案輸出的守護線程任務

import java.io.*;  

 

class TestRunnable implements Runnable{  

    public void run(){  

               try{  

                  Thread.sleep(1000);//守護線程阻塞1秒後運行  

                  File f=new File("daemon.txt");  

                  FileOutputStream os=new FileOutputStream(f,true);  

                  os.write("daemon".getBytes());  

           }  

               catch(IOException e1){  

          e1.printStackTrace();  

               }  

               catch(InterruptedException e2){  

                  e2.printStackTrace();  

           }  

    }  

}  

public class TestDemo2{  

    public static void main(String[] args) throws InterruptedException  

    {  

        Runnable tr=new TestRunnable();  

        Thread thread=new Thread(tr);  

                thread.setDaemon(true); //設定守護線程  

        thread.start(); //開始執行分進程  

    }  

}  

運行結果:檔案daemon.txt中沒有"daemon"字串。

但是如果把thread.setDaemon(true); //設定守護線程注釋掉,檔案daemon.txt是可以被寫入daemon字串的

 

  JRE判斷程式是否執行結束的標準是所有的前台執線程行完畢了,而不管後台線程的狀態,因此,在使用後台線程候一定要注意這個問題。 

但是daemon Thread實際應用在那裡呢。舉個例子,web伺服器中的Servlet,容器啟動時後台初始化一個服務線程,即調度線程,負責處理http請求,然後每個請求過來調度線程從線程池中取出一個工作者線程來處理該請求,從而實現並發控制的目的。

網上摘的一個圖,方便大家理解:

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.