天天看點

線程的幾種狀态轉換 sinat_36042530 09-17 2.5萬 線程的狀态 線程狀态轉換圖

版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。 https://blog.csdn.net/qq_34173549/article/details/79612438

線程的狀态

初始态:NEW

建立一個Thread對象,但還未調用start()啟動線程時,線程處于初始态。

運作态:RUNNABLE

在Java中,運作态包括就緒态 和 運作态。

  • 就緒态 
    • 該狀态下的線程已經獲得執行所需的所有資源,隻要CPU配置設定執行權就能運作。
    • 所有就緒态的線程存放在就緒隊列中。
  • 運作态 
    • 獲得CPU執行權,正在執行的線程。
    • 由于一個CPU同一時刻隻能執行一條線程,是以每個CPU每個時刻隻有一條運作态的線程。

阻塞态

  • 當一條正在執行的線程請求某一資源失敗時,就會進入阻塞态。
  • 而在Java中,阻塞态專指請求鎖失敗時進入的狀态。
  • 由一個阻塞隊列存放所有阻塞态的線程。
  • 處于阻塞态的線程會不斷請求資源,一旦請求成功,就會進入就緒隊列,等待執行。

PS:鎖、IO、Socket等都資源。

等待态

  • 目前線程中調用wait、join、park函數時,目前線程就會進入等待态。
  • 也有一個等待隊列存放所有等待态的線程。
  • 線程處于等待态表示它需要等待其他線程的訓示才能繼續運作。
  • 進入等待态的線程會釋放CPU執行權,并釋放資源(如:鎖)

逾時等待态

  • 當運作中的線程調用sleep(time)、wait、join、parkNanos、parkUntil時,就會進入該狀态;
  • 它和等待态一樣,并不是因為請求不到資源,而是主動進入,并且進入後需要其他線程喚醒;
  • 進入該狀态後釋放CPU執行權 和 占有的資源。
  • 與等待态的差別:到了逾時時間後自動進入阻塞隊列,開始競争鎖。

終止态

線程執行結束後的狀态。

線程狀态轉換圖

線程的幾種狀态轉換 sinat_36042530 09-17 2.5萬 線程的狀态 線程狀态轉換圖

初始态——>就緒态

當線程對象調用start()方法時就會進入就緒态,若就緒隊列沒有線程,則直接進入運作态。

就緒态——>運作态

由系統調用完成。

就緒态<——運作态

  1. 調用Thread.yield()函數
  2. 由系統調用完成(當線程時間片用完)

運作态——>阻塞态

當線程請求鎖失敗時進入阻塞态。

阻塞态——>就緒态

阻塞隊列中的線程會不斷檢查鎖是否可用,一旦可用就進入就緒隊列。

運作态——>等待态

  1. 調用Object.wait()方法 
    • wait方法必須在同步塊内部;
    • 必須由同步塊的鎖對象調用;
    • 必須由notify方法和wait方法必須由同一個鎖對象調用
  2. 調用Thread.join()方法
  3. 調用LockSupport.park()方法

等待态——>就緒态

某一個線程調用了 鎖對象.notify()方法,并且等待的線程并不需要鎖

等待态——>阻塞态

鎖對象.notify()方法,并且等待的線程需要鎖同步。

注意點

  • wait()方法會釋放CPU執行權 和 占有的鎖。
  • sleep(long)方法僅釋放CPU使用權,鎖仍然占用;線程被放入逾時等待隊列,與yield相比,它會使線程較長時間得不到運作。
  • yield()方法僅釋放CPU執行權,鎖仍然占用,線程會被放入就緒隊列,會在短時間内再次執行。
  • wait和notify必須配套使用,即必須使用同一把鎖調用;
  • wait和notify必須放在一個同步塊中
  • 調用wait和notify的對象必須是他們所處同步塊的鎖對象。