什麼是守護線程?jvm
其實在Java虛擬機中,線程分爲兩大類,分別是:用戶線程(User Thread)、守護線程(Daemon Thread)ide
守護線程是爲其餘線程服務的一種特殊線程,它獨立於終端而且週期性的執行某種任務或者等待處理某些發生的事件,它依賴於系統。spa
當JVM只存在守護線程時,JVM虛擬機會自動關閉。大多數JVM線程都是守護線程,比較經典的就是垃圾回收線程。線程
能夠經過調用 Thread.setDaemon(true)方法將用戶線程設置爲守護線程。code
public static void main(String[] args) { Thread thread = new Thread() { @Override public void run() { try { int i = 0; while (true) { System.out.println("第" + (++i) + "次在控制檯輸出信息!"); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } } }; thread.start(); System.out.println("主線程執行完畢!!!"); /** * 只是一個用戶線程, 當主線程執行完畢時,用戶線程還會繼續執行 */ }
public static void main(String[] args) { Thread thread = new Thread() { @Override public void run() { try { int i = 0; while (true) { System.out.println("第" + (++i) + "次在控制檯輸出信息!"); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } } };~~~~ /** * 設置爲守護線程 */ thread.setDaemon(true); thread.start(); System.out.println("主線程執行完畢!!!"); }
這裏留下一個疑問,圖中當打印「主線程執行完畢!!!」後,如標誌主線程已經執行完畢,那麼守護線程就不該該打印「第1次在控制檯輸出信息!」。
這裏推測jvm關閉、主線程打印信息、守護線程打印信息應該有一個前後順序。
爲了證實這個推測,咱們在打印打印「主線程執行完畢!!!」後添加手動關閉虛擬機的操做。進程
public static void main(String[] args) throws InterruptedException { Thread thread = new Thread() { @Override public void run() { try { int i = 0; while (true) { System.out.println("第" + (++i) + "次在控制檯輸出信息!"); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } } }; /** * 設置爲守護線程 */ thread.setDaemon(true); thread.start(); System.out.println("主線程執行完畢!!!"); System.exit(1);//JVM退出 }
由此可知JVM關閉是最後執行的,而守護線程與主線程執行打印與線程搶佔CPU資源有關,至於執行前後順序可能有所出入。事件
在以前看過一個帖子,守護線程可以影響finally代碼塊的執行,這裏先作一個實驗:資源
public static void main(String[] args) { try { System.out.println("執行了try代碼塊"); throw new RuntimeException("I am Runtime Exception"); } catch (Exception e) { System.out.println("執行了catch代碼塊, 錯誤信息: " + e.getMessage()); } finally { System.out.println("執行了finally代碼塊"); } }
public static void main(String[] args) { try { System.out.println("執行了try代碼塊"); throw new RuntimeException("I am Runtime Exception"); } catch (Exception e) { System.out.println("執行了catch代碼塊, 錯誤信息: " + e.getMessage()); System.exit(1);//異常關閉虛擬機 } finally { System.out.println("執行了finally代碼塊"); } }
當手動關閉JVM時,finally代碼塊將不會執行get
public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(() -> { try { System.out.println("執行了try代碼塊"); throw new RuntimeException("I am Runtime Exception"); } catch (Exception e) { System.out.println("執行了catch代碼塊, 錯誤信息: " + e.getMessage()); } finally { System.out.println("執行了finally代碼塊"); } }); thread.setDaemon(true); thread.start(); Thread.sleep(1000); System.out.println("主線程執行完畢!!!"); }
從以上實例可知,守護進程並無finally代碼塊的執行,那爲啥會影響finally代碼塊的執行呢?虛擬機
public static void main(String[] args) throws InterruptedException { Thread thread = new Thread(() -> { try { System.out.println("執行了try代碼塊"); throw new RuntimeException("I am Runtime Exception"); } catch (Exception e) { System.out.println("執行了catch代碼塊, 錯誤信息: " + e.getMessage()); System.exit(1); } finally { System.out.println("執行了finally代碼塊"); } }); thread.setDaemon(true); thread.start(); Thread.sleep(1000); System.out.println("主線程執行完畢!!!"); }
這是證實的例子,仔細看會發如今catch代碼中關閉了JVM,這個原理與異常關閉虛擬機致使finally代碼塊沒法執行同樣,所以並不能證實守護線程會影響finally代碼塊的執行~~~~