守護線程
學習的過程中偶然發現Java中居然也有守護線程這東西,感覺十分好奇,網上查閱一些資料做一些整理
加深自己的記憶,同時也方便日後的再學習。好記性不如爛博客!
JVM中存在兩種線程:用戶線程和守護線程。
所謂的守護線程,是指用戶程序在運行的時候後臺提供的一種通用服務的線程,比如用於垃圾回收的
垃圾回收線程。這類線程並不是用戶線程不可或缺的部分,只是用於提供服務的"服務線程"。
基於這個特點,當虛擬機中的用戶線程全部退出運行時,守護線程沒有服務的對象後,JVM也就退出了。
這點JDK源碼中的介紹已經說明這一點了。
* Marks this thread as either a {@linkplain #isDaemon daemon} thread
* or a user thread. The Java Virtual Machine exits when the only
* threads running are all daemon threads.
即:當線程中只剩下守護線程時JVM就會退出,反之還有任意一個用戶線程在,JVM都不會退出。下面筆者用一個實際例子來驗證下上述論點。
package com.al;
import java.util.Scanner;
public class DaemonRunner implements Runnable {
public void run() {
while (true) {
for (int i = 1; i <= 3; i++) {
System.out.println("守護線程:"+i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
Thread daemonThread = new Thread(new DaemonRunner());
// 設置爲守護進程
daemonThread.setDaemon(true);
daemonThread.start();
System.out.println("isDaemon = " + daemonThread.isDaemon());
Scanner scanner = new Scanner(System.in);
// 接受輸入,使程序在此停頓,一旦接受到用戶輸入,main線程結束,JVM退出!
scanner.next();
//AddShutdownHook方法增加JVM停止時要做處理事件:
//當JVM退出時,打印JVM Exit語句.
Runtime.getRuntime().addShutdownHook(new Thread(){
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("JVM Exit!");
}
});
}
}
我們如何開始一個自定義的守護進程呢?正如上述代碼一樣,答案很簡單,就是在Thread.start()
方法之前使用setDaemon(true)方法,通過此方法將Thread類中的boolean daemon=true;JVM就會將
該線程歸爲守護線程。而且必須注意的是根據JDK源碼的解釋,該方法必須在start方法之前調用。
* <p> This method must be invoked before the thread is started.
根據上述論點以及程序的邏輯,我們知道在我們向控制檯輸入後main線程就應該結束,從而導致
JVM退出,守護線程結束,不在打印相關語句。直接看輸出結果.
若想更加直觀的看到該情況,可以使用JDK自帶的工具jvisualvm.exe(bin目錄下)查看,下圖
是筆者的查看情況
也可以使用命令行下的jstack命令:
該命令下可以看出有哪些守護線程,哪些用戶線程了。
說完了守護線程如何產生和特點,下面簡要的談談使用守護線程應該注意的地方。
1、thread.setDaemon(true)必須在thread.start()之前設置,否則會跑出一個異常。你不能把正在運行
的常規線程設置爲守護線程。
2、在守護線程中產生的線程也是守護線程。(這點讀者可結合工具自己驗證)
3、我們自己產生的守護線程應該避免訪問一些類似於文件、數據庫等固有資源,因爲由於JVM沒有用戶
線程之後,守護線程會馬上終止。
總結就到這個地方,筆者從沒使用過java中的Daemon線程,上述總結也參照了一些網上的資源加之自己的
理解,不當之處希望指出。