1. 程式人生 > >菜鳥成長之路之Thread的SetDeamon()守護執行緒原始碼分析(4)

菜鳥成長之路之Thread的SetDeamon()守護執行緒原始碼分析(4)

    相信大家的童年都有過《西遊記》的陪伴,唐僧四人一起去西天取經的故事肯定也是耳熟能詳,在西遊記裡唐僧作為整個取經隊伍的領導者,而徒弟們跟隨師傅指引的方向去前進,這裡我們可以把取經當成是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();


	}
}