用戶執行緒和守護執行緒了解嗎?
什么是用戶執行緒和守護執行緒?
守護執行緒是一種特殊的執行緒,在后臺默默地完成一些系統性的服務,比如垃圾回收執行緒、JIT執行緒都是守護執行緒,與之對應的是用戶執行緒,用戶執行緒可以理解為是系統的作業執行緒,它會完成這個程式需要完成的業務操作,
如何手動設定執行緒為守護執行緒?
java 中的執行緒分為兩種:守護執行緒(Daemon)和用戶執行緒(User),任何執行緒都可以設定為守護執行緒和用戶執行緒,通過方法 setDaemon() 即可實作,
// 介面方法
void setDaemon(boolean on) // 將此執行緒標記為用戶執行緒,true 則把該執行緒設定為守護執行緒,反之則為用戶執行緒
boolean isDaemon() // 判斷這個執行緒是否是守護執行緒,回傳true表示守護執行緒,否則為用戶執行緒
注意點:
- 當程式中所有的用戶執行緒執行完畢之后,不管守護執行緒是否結束,系統都會自動退出;
- java執行緒分為用戶執行緒和守護執行緒,執行緒的 daemon 屬性為 true 表示是守護執行緒,false 表示是用戶執行緒;
- 設定守護執行緒:
t1.setDaemon(true),該陳述句要放在t1.start()方法執行之前,如果放在后面,會報IllegalThreadStateException例外,不起作用;
?? 1:
public class Demo {
/**
驗證:當程式中所有的用戶執行緒執行完畢之后,不管守護執行緒是否結束,系統都會自動退出
*/
static class T1 extends Thread {
public T1(String name) {
super(name);
}
@Override
public void run() {
System.out.println(this.getName() + "開始執行," + (this.isDaemon() ? "我是守護執行緒" : "我是用戶執行緒"));
while (true) ; // 死回圈
}
}
public static void main(String[] args) {
T1 t1 = new T1("t1");
t1.setDaemon(true); // 放在 t1.start() 方法執行之前,設為守護執行緒
t1.start();
System.out.println("主執行緒結束");
}
}
//------------------ 運行結果
主執行緒結束
t1開始執行,我是守護執行緒 (程式正常結束)
?? 2:
/**
驗證:設定守護執行緒,需要在start()方法之前進行
*/
public class Demo1 {
static void main(String[] args) {
Thread t1 = new Thread() {
@Override
public void run() {
try {
TimeUnit.SECONDS.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
t1.start();
t1.setDaemon(true);
}
}
//------------------ 運行結果
Exception in thread "main" java.lang.IllegalThreadStateException
at java.lang.Thread.setDaemon(Thread.java:1359)
原始碼看看
查看 Thread 的原始碼,發現 布爾型變數 daemon 是Thread類中的一個成員變數,默認值為 false,
/* Thread.java */
public class Thread implements Runnable {
......
// 布爾型變數 daemon 是Thread類中的一個成員變數,默認值為 false
private boolean daemon = false;
}
查看執行緒的 init 方法(init 方法在創建執行緒時會執行,該方法作用在Thread構造器內部),可以看出 dameon 的默認值為父執行緒的daemon,也就是說,父執行緒如果為用戶執行緒,子執行緒默認也是用戶現場;父執行緒如果是守護執行緒,子執行緒默認也是守護執行緒,
父執行緒就是創建當前執行緒的那個執行緒,比如我們經常在main函式中 new 一個 t1 執行緒,那 main 執行緒是 t1 執行緒的父執行緒,t1 是子執行緒,
/* Thread.java */
private void init(ThreadGroup g, Runnable target, String name,.......){
......
Thread parent = currentThread();
this.daemon = parent.isDaemon();
......
}
?? 1:
public class Demo2 {
static class T extends Thread {
public T(String name) {
super(name);
}
@Override
public void run() {
System.out.println(this.getName() + ".daemon:" + this.isDaemon());
}
}
public static void main(String[] args) throws InterruptedException {
// 列印 main 執行緒的狀態
System.out.println(Thread.currentThread().getName() + ".daemon:" + Thread.currentThread().isDaemon());
// main 執行緒中創建了 t1 執行緒
T t1 = new T("t1");
t1.start();
Thread t2 = new Thread() {
@Override
public void run() {
System.out.println(this.getName() + ".daemon:" + this.isDaemon());
// t2 內創建了 t3 執行緒
T t3 = new T("t3");
t3.start();
}
};
t2.setName("t2");
t2.setDaemon(true); // 手動設定 t2 為守護執行緒
t2.start();
TimeUnit.SECONDS.sleep(2);
}
}
//------------------ 運行結果
main.daemon:false
t1.daemon:false
t2.daemon:true
t3.daemon:true
總結
- java 中的執行緒分為兩種:守護執行緒(Daemon)和用戶執行緒(User);
- 當程式中所有的用戶執行緒執行完畢之后,不管守護執行緒是否結束,系統都會自動退出;
- 任何執行緒都可以設定為守護執行緒和用戶執行緒,通過方法
setDaemon(boolean on)即可實作,此外,setDaemon(boolean on)方法必須在執行緒的start()方法之前呼叫,在后面呼叫會報例外; - 執行緒的
daemon默認值和其父執行緒(創建它的執行緒)一樣; - Thread Dump 列印出來的執行緒資訊,含有 daemon 字樣的執行緒即為守護行程,常見的守護執行緒有 服務守護行程、編譯守護行程、windows 下的監聽 Ctrl+break 的守護行程、Finalizer 守護行程、參考處理守護行程、GC 守護行程,
參考
http://itsoku.com/course/1/9#目錄
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/502539.html
標籤:Java
上一篇:day24--Java集合07
下一篇:面試手撕并發演算法題
