Java 的線程在運行階段會有不一樣的狀態,在Java代碼中表現爲一個枚舉類 Thread.State
其定義以下:
前端
public enum State { // 還沒有啓動的線程狀態,通常是建立好的線程還沒有調用start() 方法局處於NEW狀態 NEW, // 線程處於可運行的狀態,表示能夠被JVM執行,可是也可能處於等待其餘資源的狀態,例如等待處理器的資源 // JVM 概述的將可運行與運行中,統稱爲RUNABLE RUNNABLE, // 線程處於阻塞狀態,表示線程正在等待獲取鎖,通常是synchronized代碼或者調用某個對象wait()方法 // 暫時獲取不到鎖,處於其餘資源釋放鎖的等待狀態 BLOCKED, /** * 線程狀態處於等待狀態,多是調用如下的方法: * <li>{@link Object#wait() Object.wait}</li> * <li>{@link #join() Thread.join} with no timeout</li> * <li>{@link LockSupport#park() LockSupport.park}</li> * * 或者是處於等待狀態的線程在等待其餘線程執行特定的動做,好比當前線程調用了某個對象的Object.wait()方法 * 該線程將會等待其餘線程調用該對象的Object.notify()方法或者Object.notifyAll()方法 * 或者調用了Thread.join()方法的線程等待其餘線程的完成,即等待其餘線程進入TERMINATED狀態 */ WAITING, /** * 線程處於有限時間的等待,通常是調用的了包含時間的等待放方法,好比下面的方法 {@link #sleep Thread.sleep} 休眠了必定的時間 {@link Object#wait(long) Object.wait} {@link #join(long) Thread.join} with timeout {@link LockSupport#parkNanos LockSupport.parkNanos} {@link LockSupport#parkUntil LockSupport.parkUntil} */ TIMED_WAITING, /** * 線程處於消亡狀態,表示線程已經執行完成。 */ TERMINATED;
經過上文的枚舉狀態說明,咱們瞭解到Java程序運行的代碼狀態的具體含義,線程在自身切換的生命週期中,並非固定處於某個狀態,而是隨着代碼的執行在不停地切換,下圖概述了Java線程的狀態切換流程。
java
NEW
NEW
進入 RUNNABLE
狀態,JVM籠統的將正在運行和等待CPU執行統稱爲 RUNNABLE
RUNABLE
, 若是設置等待超時參數,則會進入 TIMED_WAITING
狀態好比多個線程都在等待某個對象的notify()方法或者notifyAll()被調用,在恢復的時候可能就是隨機選擇一個等待該對象nofify()的線程恢復,其餘線程繼續等待,因此此處才聲明有可能恢復爲RUNABLE狀態
synchronized
關鍵字修飾的方法或者代碼塊的時候,則進入阻塞狀態通常其餘的Lock同步的話,則會進入WAITING或則TIMED_WAITING 狀態,而非 BLOCKED 狀態
TERINATED
狀態顧名思義,守護線程就是守護其餘線程的執行,當進程沒有非守護進程的時候,JVM就會退出 (只有進程中存在非守護線程,VM纔不會退出)。它主要用於在程序後臺進行調度以及其餘支持。能夠經過 Thread.setDaemon(bool)
來設置當前線程是是守護線程(傳參true)仍是用戶線程(傳參false)。該設置僅在Thread處於NEW狀態時候設置有效,不能在線程啓動以後設置。若是設置則會拋出異常 IllegalThreadStateException
。
算法
public final void setDaemon(boolean on) { checkAccess(); if (isAlive()) { throw new IllegalThreadStateException(); } daemon = on; } /** * Tests if this thread is alive. A thread is alive if it has * been started and has not yet died. */ public final native boolean isAlive();
當JVM退出的時候,守護線程並不必定會執行完畢,好比並不會執行finally方法,因此咱們並不能依賴守護線程的finally方法來進行資源的關閉或者釋放。好比下面的代碼
編程
public class DaemonThread implements Runnable { @Override public void run() { try { SleepUtils.sleep(2); } finally { // 此代碼並不會被執行 System.out.println("DaemonThread.run.finally"); } } public static void main(String[] args) { Thread thread = new Thread(new DaemonThread(), "DaemonThread"); thread.setDaemon(true); thread.start(); } }
在上一篇文章線程的建立,展現了一段線程建立的init() 方法的代碼,裏面的代碼展現了線程的是不是守護線程會被繼承到其建立的線程的,也就是說守護線程建立的線程,默認也是守護線程後端
this.daemon = parent.isDaemon();