線程的狀態轉化

線程在必定條件下,狀態會發生變化。線程一共有如下幾種狀態:html

一、新建狀態(New):新建立了一個線程對象。例如,Thread thread = new Thread()。spa

二、就緒狀態(Runnable):線程對象建立後,其餘線程調用了該對象的start()方法。該狀態的線程位於「可運行線程池」中,變得可運行,只等待獲取CPU的使用權即在就緒狀態的進程除CPU以外,其它的運行所需資源都已所有得到。例如,thread.start()。線程

三、運行狀態(Running):線程獲取CPU權限進行執行,須要注意的是,線程只能從就緒狀態進入到運行狀態。htm

四、阻塞狀態(Blocked):阻塞狀態是線程由於某種緣由放棄CPU使用權,暫時中止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。對象

阻塞的狀況分三種:繼承

  (01) 等待阻塞 -- 經過調用線程的wait()方法,該線程會釋放佔用的全部資源,JVM會把該線程放入「等待池」中。進入這個狀態後,必須依靠其餘線程調用notify()或notifyAll()方法才能被喚醒,接口

  (02) 同步阻塞 -- 線程在獲取synchronized同步鎖失敗(由於鎖被其它線程所佔用),它會進入同步阻塞狀態。生命週期

  (03) 其餘阻塞 -- 經過調用線程的sleep()或join()或發出了I/O請求時,線程會進入到阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程從新轉入就緒狀態。隊列

五、死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命週期。進程

線程變化的狀態轉換圖以下:

1. 初始狀態

實現Runnable接口和繼承Thread類能夠獲得一個線程類,new一個實例出來,線程就進入了初始狀態。

2.1. 就緒狀態

  1. 就緒狀態只是說你資格運行,調度程序沒有挑選到你,你就永遠是就緒狀態。
  2. 調用線程的start()方法,此線程進入就緒狀態。
  3. 當前線程sleep()方法結束,其餘線程join()結束,等待用戶輸入完畢,某個線程拿到對象鎖,這些線程也將進入就緒狀態。
  4. 當前線程時間片用完了,調用當前線程的yield()方法,當前線程進入就緒狀態。
  5. 鎖池裏的線程拿到對象鎖後,進入就緒狀態。

2.2. 運行中狀態

線程調度程序從可運行池中選擇一個線程做爲當前線程時線程所處的狀態。這也是線程進入運行狀態的惟一一種方式。

3. 阻塞狀態

阻塞狀態是線程阻塞在進入synchronized關鍵字修飾的方法或代碼塊(獲取鎖)時的狀態。

4. 等待

處於這種狀態的線程不會被分配CPU執行時間,它們要等待被顯式地喚醒,不然會處於無限期等待的狀態。

5. 超時等待

處於這種狀態的線程不會被分配CPU執行時間,不過無須無限期等待被其餘線程顯示地喚醒,在達到必定時間後它們會自動喚醒。

幾種方法的比較

  1. Thread.sleep(long millis),必定是當前線程調用此方法,當前線程進入TIMED_WAITING狀態,但不釋放對象鎖,millis後線程自動甦醒進入就緒狀態。做用:給其它線程執行機會的最佳方式。
  2. Thread.yield(),必定是當前線程調用此方法,當前線程放棄獲取的CPU時間片,但不釋放鎖資源,由運行狀態變爲就緒狀態,讓OS再次選擇線程。做用:讓相同優先級的線程輪流執行,但並不保證必定會輪流執行。實際中沒法保證yield()達到讓步目的,由於讓步的線程還有可能被線程調度程序再次選中。Thread.yield()不會致使阻塞。該方法與sleep()相似,只是不能由用戶指定暫停多長時間。
  3. t.join()/t.join(long millis),當前線程裏調用其它線程t的join方法,當前線程進入WAITING/TIMED_WAITING狀態,當前線程不會釋放已經持有的對象鎖。線程t執行完畢或者millis時間到,當前線程進入就緒狀態。
  4. obj.wait(),當前線程調用對象的wait()方法,當前線程釋放對象鎖,進入等待隊列。依靠notify()/notifyAll()喚醒或者wait(long timeout) timeout時間到自動喚醒。
  5. obj.notify()喚醒在此對象監視器上等待的單個線程,選擇是任意性的。notifyAll()喚醒在此對象監視器上等待的全部線程。
相關文章
相關標籤/搜索