您好,登錄后才能下訂單哦!
守護線程是一種特殊的線程,在后臺默默地完成一些系統性的服務,比如垃圾回收線程、JIT線程都是守護線程。與之對應的是用戶線程,用戶線程可以理解為是系統的工作線程,它會完成這個程序需要完成的業務操作。如果用戶線程全部結束了,意味著程序需要完成的業務操作已經結束了,系統可以退出了。所以當系統只剩下守護進程的時候,java虛擬機會自動退出。
java線程分為用戶線程和守護線程,線程的daemon屬性為true表示是守護線程,false表示是用戶線程。
下面我們來看一下守護線程的一些特性。
package com.itsoku.chat03;
/**
* 微信公眾號:javacode2018,獲取年薪50萬課程
*/
public class Demo1 {
public 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("子線程1");
t1.start();
System.out.println("主線程結束");
}
}
運行上面代碼,結果如下:
可以看到主線程已經結束了,但是程序無法退出,原因:子線程1是用戶線程,內部有個死循環,一直處于運行狀態,無法結束。
再看下面的代碼:
package com.itsoku.chat03;
/**
* 微信公眾號:javacode2018,獲取年薪50萬課程
*/
public class Demo2 {
public 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("子線程1");
t1.setDaemon(true);
t1.start();
System.out.println("主線程結束");
}
}
運行結果:
程序可以正常結束了,代碼中通過t1.setDaemon(true);
將t1線程設置為守護線程,main方法所在的主線程執行完畢之后,程序就退出了。
結論:當程序中所有的用戶線程執行完畢之后,不管守護線程是否結束,系統都會自動退出。
package com.itsoku.chat03;
import java.util.concurrent.TimeUnit;
/**
* 微信公眾號:javacode2018,獲取年薪50萬課程
*/
public class Demo3 {
public 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);
}
}
t1.setDaemon(true);
是在t1的start()方法之后執行的,執行會報異常,運行結果如下:
我們看一下創建線程源碼,位于Thread類的init()方法中:
Thread parent = currentThread();
this.daemon = parent.isDaemon();
dameon的默認值為為父線程的daemon,也就是說,父線程如果為用戶線程,子線程默認也是用戶現場,父線程如果是守護線程,子線程默認也是守護線程。
示例代碼:
package com.itsoku.chat03;
import java.util.concurrent.TimeUnit;
/**
* 微信公眾號:javacode2018,獲取年薪50萬課程
*/
public class Demo4 {
public static class T1 extends Thread {
public T1(String name) {
super(name);
}
@Override
public void run() {
System.out.println(this.getName() + ".daemon:" + this.isDaemon());
}
}
public static void main(String[] args) throws InterruptedException {
System.out.println(Thread.currentThread().getName() + ".daemon:" + Thread.currentThread().isDaemon());
T1 t1 = new T1("t1");
t1.start();
Thread t2 = new Thread() {
@Override
public void run() {
System.out.println(this.getName() + ".daemon:" + this.isDaemon());
T1 t3 = new T1("t3");
t3.start();
}
};
t2.setName("t2");
t2.setDaemon(true);
t2.start();
TimeUnit.SECONDS.sleep(2);
}
}
運行代碼,輸出:
main.daemon:false
t1.daemon:false
t2.daemon:true
t3.daemon:true
t1是由主線程(main方法所在的線程)創建的,main線程是t1的父線程,所以t1.daemon為false,說明t1是用戶線程。
t2線程調用了setDaemon(true);
將其設為守護線程,t3是由t2創建的,所以t3默認線程類型和t2一樣,t2.daemon為true。
java高并發系列連載中,總計估計會有四五十篇文章,可以關注公眾號:javacode2018,獲取最新文章。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。