菜鳥成長之路之Thread的SetDeamon()守護執行緒原始碼分析(4)
阿新 • • 發佈:2018-12-16
相信大家的童年都有過《西遊記》的陪伴,唐僧四人一起去西天取經的故事肯定也是耳熟能詳,在西遊記裡唐僧作為整個取經隊伍的領導者,而徒弟們跟隨師傅指引的方向去前進,這裡我們可以把取經當成是Thread執行的終點,師傅作為被守護執行緒,徒弟作為守護執行緒,當取完經後或者師傅不去取經了,那麼徒弟們的任務也就跟著完成了。也就是講,當被守護執行緒結束後,守護執行緒也就跟著結束掉了,接下來,我們來看下Thread裡面的守護執行緒吧。
isDaemon() -- 測試該執行緒是否為守護執行緒,如果該執行緒是守護執行緒,則返回 true
;否則返回 false
。
setDaemon(boolean on)--
將該執行緒標記為守護執行緒或使用者執行緒。當正在執行的執行緒都是守護執行緒時,Java 虛擬機器退出。
該方法必須在啟動執行緒前呼叫。
該方法首先呼叫該執行緒的 checkAccess
方法,且不帶任何引數。這可能丟擲 SecurityException
(在當前執行緒中)。
然後,我們來看下SetDaemon()
public final void setDaemon(boolean on) { checkAccess(); if (isAlive()) { throw new IllegalThreadStateException(); } daemon = on; }
這裡,isAlive()是
測試執行緒是否處於活動狀態。如果執行緒已經啟動且尚未終止,則為活動狀態。
返回:
如果該執行緒處於活動狀態,則返回 true
;否則返回 false
。
這裡說明,SetDaemon()只能在執行緒為開啟時呼叫。
而checkAccess()是
判定當前執行的執行緒是否有權修改該執行緒。
如果有安全管理器,則呼叫其 checkAccess
方法,並將該執行緒作為其引數。這可能導致丟擲 SecurityException
。
接下來我們來做個案例:
class StopThread01 implements Runnable { @Override public void run() { while (true) { try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "...run"); } } } public class SetDeamonDemo { public static void main(String[] args) { StopThread01 st = new StopThread01(); Thread t1 = new Thread(st); t1.setDaemon(true);//守護執行緒 主執行緒結束,此執行緒也結束 t1.start(); int num = 0; while (true){ try { if(num++ == 6){ break; } Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"..."+num); } System.out.println("over"); } }
我們來檢視結果:
這裡當main執行緒執行完後,守護執行緒也就跟著結束掉了。
那麼我們線上程開啟後再呼叫SetDaemon()會怎麼樣呢?請看
我們把兩個程式碼調換下位置,發現控制檯列印,
而當我們在守護執行緒內部再定義一個執行緒時,當被守護執行緒結束後,守護執行緒及守護執行緒內的執行緒也會跟著結束。
下面貼出程式碼:
public class SetDeamonDemo01 {
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
Thread child = new Thread(new Runnable() {
@Override
public void run() {
new Thread(new Runnable() {
@Override
public void run() {
while(true){
System.out.println(Thread.currentThread().getName()+"da da da");
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
},"myThreadChild02").start();
try {
while (true){
System.out.println("di di di");
Thread.sleep(10);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
},"myThreadChild01");
child.setDaemon(true);
child.start();
//休眠5秒
try {
Thread.sleep(5_000);
System.out.println("parent Thread is dead...");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}