更新時間:2020-11-24 17:29:39 來源:動力節(jié)點 瀏覽1550次
在Java多線程環(huán)境中,為保證所有線程的執(zhí)行能按照一定的規(guī)則執(zhí)行,JVM實現(xiàn)了一個線程調(diào)度器,它定義了線程調(diào)度的策略,對于CPU運算的分配都進行了規(guī)定,按照這些特定的機制為多個線程分配CPU的使用權。Java線程調(diào)度是Java多線程的核心,只有良好的調(diào)度,才能充分發(fā)揮系統(tǒng)的性能,提高程序的執(zhí)行效率。
線程調(diào)度是指系統(tǒng)為線程分配處理器使用權的過程,Java使用的線程調(diào)度方式就是搶占式調(diào)度,線程調(diào)度主要方式有兩種:
1.協(xié)同式 (Cooperative Threads-Scheduling)線程調(diào)度:
使用協(xié)同式調(diào)度的多線程系統(tǒng),線程的執(zhí)行時間由線程本身來控制,線程把自己的工作執(zhí)行完了之后,要主動通知系統(tǒng)切換到另外一個線程上去。協(xié)同式多線程的最大好處是實現(xiàn)簡單,而且由于線程要把自己的事情干完后才會進行線程切換,切換操作對線程自己是可知的,所以一般沒有什么 線程同步的問題。它的壞處也很明顯:線程執(zhí)行時間不可控制,甚至如果一個線程的代碼編寫有問題,一直不告知系統(tǒng)進行線程切換,那么程序就會一直阻塞在那里。
2.搶占式(Preemptive Threads-Scheduling)線程調(diào)度
使用搶占式調(diào)度的多線程系統(tǒng),那么每個線程將由系統(tǒng)來分配執(zhí)行時間,線程的切換不由 程本身來決定。譬如在Java中,有Thread::yield()方法可以主動讓出執(zhí)行時間,但是如果想要主動獲取執(zhí)行時間,線程本身是沒有什么辦法的。在這種實現(xiàn)線程調(diào)度的方式下,線程的執(zhí)行時間是系統(tǒng)可控的,也不會有一個線程導致整個進程甚至整個系統(tǒng)阻塞的問題。
在了解了兩種線程調(diào)度模式后,現(xiàn)在考慮Java使用的是哪種線程調(diào)度模式。此問題的討論涉及到JVM的實現(xiàn),JVM規(guī)范中規(guī)定每個線程都有優(yōu)先級,且優(yōu)先級越高越優(yōu)先執(zhí)行,但優(yōu)先級高并不代表能獨自占用執(zhí)行時間片,可能是優(yōu)先級高得到越多的執(zhí)行時間片,反之,優(yōu)先級低的分到的執(zhí)行時間少但不會分配不到執(zhí)行時間。JVM的規(guī)范沒有嚴格地給調(diào)度策略定義,我想正是因為面對眾多不同調(diào)度策略,JVM要封裝所有細節(jié)提供一個統(tǒng)一的策略不太現(xiàn)實,于是給了一個不嚴謹?shù)銐蚪y(tǒng)一的定義?;氐絾栴}上,Java使用的線程調(diào)度是搶占式調(diào)度,在JVM中體現(xiàn)為讓可運行池中優(yōu)先級高的線程擁有CPU使用權,如果可運行池中線程優(yōu)先級一樣則隨機選擇線程,但要注意的是實際上一個絕對時間點只有一個線程在運行(這里是相對于一個CPU來說,如果你的機器是多核的還是可能多個線程同時運行的),直到此線程進入非可運行狀態(tài)或另一個具有更高優(yōu)先級的線程進入可運行線程池,才會使之讓出CPU的使用權,更高優(yōu)先級的線程搶占了優(yōu)先級低的線程的CPU。
Java的線程的調(diào)度機制都由JVM實現(xiàn),假如有若干條線程,你想讓某些線程擁有更長的執(zhí)行時間,或某些線程分配少點執(zhí)行時間,這時就涉及“線程優(yōu)先級”。由于JVM的實現(xiàn)以宿主操作系統(tǒng)為基礎,所以Java優(yōu)先級值與各種不同操作系統(tǒng)的原生線程優(yōu)先級必然存在某種映射關系,這樣才足以封裝所有操作系統(tǒng)的優(yōu)先級提供統(tǒng)一優(yōu)先級語義。
Java線程調(diào)度策略決定上層多線程運行機制,JVM的線程調(diào)度器實現(xiàn)了搶占式調(diào)度,每條線程執(zhí)行的時間由它分配管理,它將按照線程優(yōu)先級的建議對線程執(zhí)行的時間進行分配,優(yōu)先級越高,可能得到CPU的時間則越長。但是,不管程序員怎么編寫調(diào)度,只能最大限度的影響線程執(zhí)行的次序,而不能做到精準控制。