線程間的調度和狀態轉換關系


線程的調度

線程的調度是指系統為線程分配處理器使用權的過程,主要調度方式有兩種

協同式線程調度

線程執行時間由線程本身來控制,線程把自己的工作執行完了之后,要主動通知系統切到另一個線程上。

協調式多線程的最大的好處是實現簡單,而且由於線程要把自己的事情干完之后才會進行線程切換,切換操作對線程自己是可知的,所以沒有什么線程同步的問題。

缺點也很明顯:線程執行時間不可控制,如果有一個線程編寫有問題,一直不告知系統進行線程切換,那么程序就會一直阻塞在那里。

搶占式線程調度

每個線程將由系統分配執行時間,線程的切換不由線程本身來決定(JAVA中,Thread.yield()可以讓出執行時間)

雖然java線程調度是系統自動完成的,但是我們還是可以"建議"系統給某些線程多一些執行時間,這項操作可以通過設置線程優先級完成(Thread.MIN_PRIORITY致Thread.Thread.MAX_PRIORITY)

線程狀態轉換關系

線程狀態圖有助於我們記憶線程一些方法。

java語言定義了5種線程狀態,在任意一個時間點,一個線程只能有且只有其中的一種狀態,這5種狀態分別如下。

1)新建(New):

創建后尚未啟動的線程處於這種狀態。

2)運行(Runable):

Runable包括了操作系統線程狀態中的Running和Ready,也就是處於此狀態的線程有可能正在執行,也有可能等待着CPU為它分配執行時間,所謂的Ready(就緒)狀態 指的在CPU的等待隊列里面。

Thread.yield()會從Running 狀態—>Ready狀態。yield(): 當前線程會做出讓出CPU使用的暗示,但是線程調度器可能會忽略這個暗示

3)等待(Waiting):

無限期等待(Waiting):

處於這種狀態的線程不會被分配CPU執行時間,它們要等待被其他線程顯式地喚醒。以下方法會讓線程陷入無限期的等待狀態

   沒有設置Timeout參數的Object.wait()方法

wait():的目的是為了多個線程搶資源的時候,當前線程把資源讓出來

如果沒有鎖,就不存在兩個線程搶資源的情況,也就沒有必要把資源讓出來,兩個線程早就一起跑了 這也很好解釋了為什么wait方法synchronized關鍵字連用。

   沒有設置Timeout參數的Thread.join()方法

join():合並某個線程,他調用此方法的線程(別的線程)合並到當前線程上來。等待調用此方法的線程執行完了,當前線程才開始繼續執行(經常用於等待另外一個線程的結束,有點像方法調用)。

   LockSupport.park()方法 參考LockSupport實現生產者與消費者

限期等待(Time Waiting):

處於這種狀態的線程也不會被CPU分配執行時間,不過無須等待被其他線程顯式的喚醒,在一定時間之后它們會由系統自動喚醒。以下方法會讓線程進入限期等待的狀態

   Thread.sleep()方法

sleep():的過程之中 如果對當前對象加鎖了(可以不加),不會釋放當前對象的鎖。

   設置了Timeout的Object.wait()方法

   設置了TImeout的Thread.join()方法

   LockSupport.parkBanos()方法和LockSupport.parkUntil()方法

4)阻塞(Blocked): 

"阻塞狀態"與"等待狀態"的區別是:阻塞狀態在等待着獲取到一個排他鎖,等待着一個進入同步代碼塊的鎖;而等待狀態則是等待一段時間,或者喚醒動作的發生。

5)結束(Terminated):

已經終止線程的狀態,線程已經結束執行。

上述5種狀態在遇到特定事件發生的時候會互相轉換,它們之間的關系如下圖所示:


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM