java中線程分為兩種類型:用戶線程和守護線程。通過Thread.setDaemon(false)設置為用戶線程;通過Thread.setDaemon(true)設置為守護線程。如果不設置次屬性,默認為用戶線程。
用戶線程和守護線程的區別:
1. 主線程結束后用戶線程還會繼續運行,JVM存活;主線程結束后守護線程和JVM的狀態又下面第2條確定。
2.如果沒有用戶線程,都是守護線程,那么JVM結束(隨之而來的是所有的一切煙消雲散,包括所有的守護線程)。
補充說明:
定義:守護線程--也稱“服務線程”,在沒有用戶線程可服務時會自動離開。
優先級:守護線程的優先級比較低,用於為系統中的其它對象和線程提供服務。
設置:通過setDaemon(true)來設置線程為“守護線程”;將一個用戶線程設置為守護線程的方式是在線程啟動用線程對象的setDaemon方法。
example: 垃圾回收線程就是一個經典的守護線程,當我們的程序中不再有任何運行的Thread,程序就不會再產生垃圾,垃圾回收器也就無事可做,所以當垃圾回收線程 是JVM上僅剩的線程時,垃圾回收線程會自動離開。它始終在低級別的狀態中運行,用於實時監控和管理系統中的可回收資源。
生命周期:守護進程(Daemon)是運行在后台的一 種特殊進程。它獨立於控制終端並且周期性地執行某種任務或等待處理某些發生的事件。也就是說守護線程不依賴於終端,但是依賴於系統,與系統“同生共死”。 那Java的守護線程是什么樣子的呢。當JVM中所有的線程都是守護線程的時候,JVM就可以退出了;如果還有一個或以上的非守護線程則JVM不會退出。
用戶線程和守護線程的測試案例:

package com.sxf.test.thread; import java.util.Date; /** * 測試用戶線程和守護線程的區別 * @author sxf * */ public class DaemonThreadTest { public static void main(String[] args) { //測試守護線程 //testDaemonThread(); //測試用戶線程 testUserThread(); //主線程休眠5秒后退出 try { Thread.sleep(5000L); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } System.out.println("DaemonThreadTest.main()主線程退出"); } /** * 測試守護線程結果: *I'm running at Tue Dec 26 16:37:32 CST 2017, I am daemon *I'm running at Tue Dec 26 16:37:33 CST 2017, I am daemon *I'm running at Tue Dec 26 16:37:34 CST 2017, I am daemon *I'm running at Tue Dec 26 16:37:35 CST 2017, I am daemon *I'm running at Tue Dec 26 16:37:36 CST 2017, I am daemon *DaemonThreadTest.main()主線程退出 */ public static void testDaemonThread(){ DaemonThead t=new DaemonThead(); Thread thread=new Thread(t); thread.setDaemon(true);//將當前線程設置為守護線程 thread.start();//啟動當前線程 } /** * 測試用戶線程結果: * I'm running at Tue Dec 26 16:41:37 CST 2017, I am not daemon *I'm running at Tue Dec 26 16:41:38 CST 2017, I am not daemon *I'm running at Tue Dec 26 16:41:39 CST 2017, I am not daemon *I'm running at Tue Dec 26 16:41:40 CST 2017, I am not daemon *I'm running at Tue Dec 26 16:41:41 CST 2017, I am not daemon *DaemonThreadTest.main()主線程退出 *I'm running at Tue Dec 26 16:41:42 CST 2017, I am not daemon *I'm running at Tue Dec 26 16:41:43 CST 2017, I am not daemon *I'm running at Tue Dec 26 16:41:44 CST 2017, I am not daemon *I'm running at Tue Dec 26 16:41:45 CST 2017, I am not daemon *I'm running at Tue Dec 26 16:41:46 CST 2017, I am not daemon *I'm running at Tue Dec 26 16:41:47 CST 2017, I am not daemon */ public static void testUserThread(){ UserThead u=new UserThead(); Thread userThread=new Thread(u); userThread.setDaemon(false);//可不用設置,默認為用戶線程 userThread.start(); } } /** * 守護線程 * @author sxf * */ class DaemonThead implements Runnable{ @Override public void run() { String daemon = (Thread.currentThread().isDaemon() ? "daemon": "not daemon"); while (true) { System.out.println("I'm running at " + new Date() + ", I am " + daemon); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("I was interrupt, I am " + daemon); } } } } /** * 用戶線程 * @author sxf * */ class UserThead implements Runnable{ @Override public void run() { String daemon = (Thread.currentThread().isDaemon() ? "daemon": "not daemon"); while (true) { System.out.println("I'm running at " + new Date() + ", I am " + daemon); try { Thread.sleep(1000); } catch (InterruptedException e) { System.out.println("I was interrupt, I am " + daemon); } } } }