java併發編程-線程生命週期

線程生命週期

現代操作系統在運行一個程序時,會爲其創建一個進程。例如,啓動一個Java程序,操作系統就會創建一個Java進程。現代操作系統調度的最小單元是線程,也叫輕量級進程(Light Weight Process),在一個進程裏可以創建多個線程,這些線程都擁有各自的計數器、堆棧和局部變量等屬性,並且能夠訪問共享的內存變量。處理器在這些線程上高速切換,讓使用者感覺到這些線程在同時執行。

CPU再切換線程是會導致線程存在各種狀態,線程從創建到死亡其中存在不同的生命狀態;本文將對線程生命週期進行全面的介紹。

 

Java線程的狀態可以從java.lang.Thread的內部枚舉類java.lang.Thread$State得知:

public enum State {
      
    NEW,

    RUNNABLE,

    BLOCKED,

    WAITING,

    TIMED_WAITING,

    TERMINATED;
}

 

當線程被創建並啓動以後,它既不是一啓動就進入了執行狀態,也不是一直處於執行狀態。在線程的生命週期中,它要經過 新建(New)、就緒(Runnable)、運行(Running)、阻塞(Blocked、WATING、TIMED_WATING)和死亡(Dead)5種狀態。尤其是當線程啓動以後,它不可能一直"霸佔"着CPU獨自運行,所以CPU需要在多條線程之間切換,於是 線程狀態也會多次在運行、阻塞之間切換

  • 新建狀態(New)

    API註釋: 

    /**
     * Thread state for a thread which has not yet started. 
     * 線程實例尚未啓動時候的線程狀態
     */
    NEW,

    當線程對象創建後,即進入新建狀態,如:Thread t = new MyThread();

  • 就緒狀態(Runnable)

    API註釋

    /**
     * Thread state for a runnable thread.  A thread in the runnable
     * state is executing in the Java virtual machine but it may
     * be waiting for other resources from the operating system
     * such as processor.
     */
    RUNNABLE,
    
    可運行狀態下線程的線程狀態。可運行狀態下的線程在Java虛擬機中執行,但它可能執行等待操作系統的其他資源,例如處理器。

    當調用線程對象的start()方法時,線程即進入就緒狀態。處於就緒狀態的線程只是說明此線程已經做好準備,隨時等待CPU調度執行,並不是說執行了start()方法就立即執行。

    當Java線程實例調用了Thread#start()之後,就會進入RUNNABLE狀態。RUNNABLE狀態可以認爲包含兩個子狀態:READYRUNNING

    • READY:該狀態的線程可以被線程調度器進行調度使之更變爲RUNNING狀態。
    • RUNNING:該狀態表示線程正在運行,線程對象的run()方法中的代碼所對應的的指令正在被CPU執行。
    • 當Java線程實例Thread#yield()方法被調用時或者由於線程調度器的調度,線程實例的狀態有可能由RUNNING轉變爲READY,但是從線程狀態Thread#getState()獲取到的狀態依然是RUNNABLE。例如:
    • public class ThreadState1 {
      
          public static void main(String[] args) throws Exception {
              Thread thread = new Thread(()-> {
                  while (true){
                      Thread.yield();
                  }
              });
              thread.start();
              Thread.sleep(2000);
              System.out.println(thread.getState());
          }
      }
      // 輸出結果
      RUNNABLE

       

  • 運行狀態(Running)

    當CPU開始調度處於就緒狀態的線程時,此時線程才得以真正執行,即進入到運行狀態。

  • WATING狀態

         WAITING無限期的等待狀態,這種狀態下的線程不會被分配CPU執行時間。當一個線程執行了某些方法之後就會進入無限期等待狀態,直到被顯式喚醒,被喚醒後,線程狀態由WAITING更變爲RUNNABLE然後繼續執行。

  • TIMED WATING狀態

         TIMED WAITING就是有限期等待狀態,它和WAITING有點相似,這種狀態下的線程不會被分配CPU執行時間,不過這種狀態下的線程不需要被顯式喚醒,只需要等待超時限期到達就會被VM喚醒,有點類似於現實生活中的鬧鐘。

 
  • 阻塞狀態(Blocked)

處於運行狀態中的線程由於某種原因,暫時放棄對CPU的使用權,停止執行,此時進入阻塞狀態,直到其進入到就緒狀態,纔有機會再次被CPU調用以進入到運行狀態。

阻塞狀態分類

  1. 等待阻塞:運行狀態中的線程執行wait()方法,使本線程進入到等待阻塞狀態;
  2. 同步阻塞:線程在獲取synchronized同步鎖失敗(因爲鎖被其它線程佔用),它會進入到同步阻塞狀態;
  3. 其他阻塞:通過調用線程的sleep()或join()或發出I/O請求時,線程會進入到阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。
  • 死亡狀態

    線程執行完畢或者是異常退出,該線程結束生命週期。

線程相關方法
 

public class Thread{
    // 線程的啓動
    public void start(); 
    // 線程體
    public void run(); 
    // 已廢棄
    public void stop(); 
    // 已廢棄
    public void resume(); 
    // 已廢棄
    public void suspend(); 
    // 在指定的毫秒數內讓當前正在執行的線程休眠
    public static void sleep(long millis); 
    // 同上,增加了納秒參數
    public static void sleep(long millis, int nanos); 
    // 測試線程是否處於活動狀態
    public boolean isAlive(); 
    // 中斷線程 - 進入阻塞狀態
    public void interrupt(); 
    // 測試線程是否已經中斷
    public boolean isInterrupted(); 
    // 測試當前線程是否已經中斷
    public static boolean interrupted(); 
    // 等待該線程終止
    public void join() throws InterruptedException; 
    // 等待該線程終止的時間最長爲 millis 毫秒
    public void join(long millis) throws InterruptedException; 
    // 等待該線程終止的時間最長爲 millis 毫秒 + nanos 納秒
    public void join(long millis, int nanos) throws InterruptedException; 
}

 

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