線程調度是指系統(tǒng)分配處理器使用權的過程,主要調度方式有兩種,分別是協(xié)同式線程調度(Cooperative Threads-Scheduling)和搶占式線程調度(Preemptive Threads-Scheduling)。
協(xié)同式調度
使用協(xié)同式調度的多線程系統(tǒng),線程的執(zhí)行時間由線程本身來控制,線程把自己的工作執(zhí)行完了之后,要主動通知系統(tǒng)切換到另一個線程上。協(xié)同式多線程的最大好處是實現(xiàn)簡單,不會有線程同步問題。缺點是線程執(zhí)行時間不可控制,甚至如果一個線程編寫有問題,一直不告知系統(tǒng)進行線程切換,那么程序就會一直阻塞在那里。
搶占式調度
使用搶占式調度的多線程系統(tǒng),每個線程將由系統(tǒng)來分配執(zhí)行時間,線程的切換不由線程本身來決定(在Java中,Thread.yield()可以讓出執(zhí)行時間,但是要獲取執(zhí)行時間的話,線程本身是沒有什么辦法的)。在這種實現(xiàn)線程調度的方式下,線程的執(zhí)行時間是系統(tǒng)可控的,也不會有一個線程導致整個進程阻塞的問題,Java使用的線程調度方式就是搶占式調度。
狀態(tài)轉換
Java語言定義了5中線程狀態(tài),在任意yge時間點,一個線程只能有且只有其中的一種狀態(tài)。這5中狀態(tài)分別如下:
- 新建(New):創(chuàng)建后傷胃啟動的線程處于這種狀態(tài)。
- 運行(Runable):Runable包括了操作系統(tǒng)中的Running和Ready,也就是處于此狀態(tài)的線程有可能正在執(zhí)行,也有可能正在等待著CPU為它分配執(zhí)行時間。
- 無限期等待(Waiting):處于這種狀態(tài)的線程不會被分配CPU執(zhí)行時間,他們要等待被其他線程顯式地喚醒。以下方法會讓線程陷入無限期的等待:
- 沒有設置Timeout參數(shù)的Object.wait()方法
- 沒有設置Timeout參數(shù)的Thread.join()方法
- LockSupport.park()方法
- 限期等待(Timed Waiting):處于這種狀態(tài)的線程也不會被分配CPU執(zhí)行時間,不過無須等待被其他線程顯示地喚醒,在一定時間之后它們會由系統(tǒng)自動喚醒。以下方法會讓線程進入限期等待狀態(tài):
- Thread.sleep()方法。
- 設置了Timeout參數(shù)的Object.wait()方法。
- 設置了Timeout參數(shù)的Thread.join()方法。
- LockSupport.parkNanos()方法。
- LockSupport.parkUntil()方法。
- 阻塞(Blocked):線程被阻塞了,“阻塞狀態(tài)”與“等待狀態(tài)”的區(qū)別是:“阻塞狀態(tài)”在等待著獲取到一個排他鎖,這個事件將在另外一個線程放棄這個鎖的時候發(fā)生:而“等待狀態(tài)”則是在等待一段時間,或者喚醒動作發(fā)生。在程序等待進入同步區(qū)域的時候,線程將進入這種狀態(tài)。
- 結束(Terminated):已終止線程的線程狀態(tài),線程已經結束執(zhí)行。

image