在java中有兩類線程:用戶線程和守護線程(User Thread 和 Daemon Thread)。
守護線程:
守護線程是運行在後臺的一種特殊進程,它獨立於控制終端,並且週期性地執行某種任務或着等待處理某些發生的事件。也就是在程序運行的時候在後臺提供一種通用服務的線程,在沒有用戶線程客服務時會自動離開。
生命週期:守護線程並不是程序中不可缺少的部分。當所有的非守護線程即用戶線程結束,程序也就終止了,同時還會kill掉進程中的所有守護線程。
守護線程的優先級比較低,用於爲系統中的其它對象和線程提供服務。
例子:就像 垃圾回收線程一樣,當程序中不存在任何運行的線程了,程序就不會產生垃圾,垃圾回收器也就無事可做,所以當垃圾回收器是jvm上僅存的線程時,垃圾回收線程會自動離開,它始終在低級別的狀態中運行,用於實時監控和管理系統中的可回收資源。
守護線程和用戶線程的主要區別
守護線程和用戶線程的主要區別在於虛擬機的離開:如在用戶線程全部退出運行,只剩下守護線程存在了的時候,虛擬機也就退出了。守護線程 顧名思義,需要具有守護對象,守護對象沒了,守護線程也就失去了工作,所以也就沒有繼續運行程序的必要了。
守護線程的實現:
在Java中java.lang.Thread.isDaemon()方法用來測試線程是否爲守護線程。
聲明方法爲:
public final boolean isDaemon()
如果結果返回True該線程就是守護線程
注意:
- Thread.Daemon(true) 必須在Thread.start()方法之前設置,否則會出現IllegalThreadStateException異常
- 不能把正在運行的常規線程設置爲守護線程
- 守護線程應該永遠不去訪問固有資源,如:數據庫、文件等。因爲它會在任何時候甚至在一個操作的中間發生中斷。
示例:
官方示例:
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);
}
}
}