Java 多線程之 - 守護線程 java.lang.Thread.isDaemon()方法

在java中有兩類線程:用戶線程和守護線程(User Thread 和 Daemon Thread)。

守護線程:

守護線程是運行在後臺的一種特殊進程,它獨立於控制終端,並且週期性地執行某種任務或着等待處理某些發生的事件。也就是在程序運行的時候在後臺提供一種通用服務的線程,在沒有用戶線程客服務時會自動離開。

生命週期:守護線程並不是程序中不可缺少的部分。當所有的非守護線程即用戶線程結束,程序也就終止了,同時還會kill掉進程中的所有守護線程。
守護線程的優先級比較低,用於爲系統中的其它對象和線程提供服務。

例子:就像 垃圾回收線程一樣,當程序中不存在任何運行的線程了,程序就不會產生垃圾,垃圾回收器也就無事可做,所以當垃圾回收器是jvm上僅存的線程時,垃圾回收線程會自動離開,它始終在低級別的狀態中運行,用於實時監控和管理系統中的可回收資源。

守護線程和用戶線程的主要區別

守護線程和用戶線程的主要區別在於虛擬機的離開:如在用戶線程全部退出運行,只剩下守護線程存在了的時候,虛擬機也就退出了。守護線程 顧名思義,需要具有守護對象,守護對象沒了,守護線程也就失去了工作,所以也就沒有繼續運行程序的必要了。

守護線程的實現:

在Java中java.lang.Thread.isDaemon()方法用來測試線程是否爲守護線程。
聲明方法爲:

public final boolean isDaemon()

如果結果返回True該線程就是守護線程

注意:

  1. Thread.Daemon(true) 必須在Thread.start()方法之前設置,否則會出現IllegalThreadStateException異常
  2. 不能把正在運行的常規線程設置爲守護線程
  3. 守護線程應該永遠不去訪問固有資源,如:數據庫、文件等。因爲它會在任何時候甚至在一個操作的中間發生中斷。

示例:

官方示例:

package com.test.mutlithread;

public class DaemonThreadTest extends Thread {

    DaemonThreadTest() {
        setDaemon(true);
    }

    public static void main(String[] args) {
        Thread thread = new DaemonThreadTest();
        System.out.println("thread = " + thread.currentThread());//返回對當前正在執行的線程對象的引用

     // this will call run() method
        thread.start();
    }

    public void run() {
        boolean d = isDaemon();
        System.out.println("isDaemon = " + d);
    }

}

輸出:

thread = Thread[main,5,main]
isDaemon = true

常見的一個關於守護線程的例子,更容易理解:

package com.test.mutlithread;

public class DaemonThreadTest_2 extends Thread {


    public static void main(String[] args) {
        DaemonThreadTest_2 test = new DaemonThreadTest_2();
        // 如果不設置daemon,那麼線程將輸出100後才結束
        test.setDaemon(true);
        test.start();
        System.out.println("isDaemon = " + test.isDaemon());
        //        try {
//            System.in.read(); // 接受輸入,使程序在此停頓,一旦接收到用戶輸入,main線程結束,守護線程自動結束
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
        TimeUnit.SECONDS.sleep(1);
        System.out.println("isDaemon test");
    }

    public void run() {
        for (int i = 0; i < 100; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(i);
        }
    }

}

輸出:

isDaemon = true
0
1
2
3
4
5
6
7
8
isDaemon test

會打印出0-99所有的數字,該程序接受輸入,一旦接收到用戶輸入,main線程結束,守護線程自動結束。
注意:
如果把 System.in.read(); 註釋掉,即主線程方法被註釋,那麼當前程序不會打印出任何數字,也就是沒有執行run()方法,因爲主線程直接結束,導致守護線程也結束,程序終止。

或着:

package com.test.mutlithread;

import java.io.IOException;

public class DaemonThreadTest_3 extends Thread {

    DaemonThreadTest_3() {
        this.setDaemon(true);
        this.setName("myTest-DaemonThreadTest_3-" + this.getId());
    }

    public static void main(String[] args) {
        DaemonThreadTest_3 test = new DaemonThreadTest_3();
//        test.setDaemon(true);//調試時可以設置爲false,那麼這個程序是個死循環,沒有退出條件。設置爲true,即可主線程結束,test線程也結束。
        test.start();

        System.out.println("isDaemon = " + test.isDaemon());
        System.out.println("Thread Name is :" + test.getName());
        try {
            System.in.read();// 接受輸入,使程序在此停頓,一旦接收到用戶輸入,main線程結束,守護線程自動結束
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public void run() {// 永真循環線程
        for (int i = 0;; i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ex) {
            }
            System.out.println(i);
        }
    }

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章