Java執行緒的CPU時間片

超人汪小建發表於2018-04-29

Java中執行緒會按優先順序分配CPU時間片執行,那麼執行緒什麼時候放棄CPU的使用權?可以歸類成三種情況:

  1. 當前執行執行緒主動放棄CPU,JVM暫時放棄CPU操作(基於時間片輪轉排程的JVM作業系統不會讓執行緒永久放棄CPU,或者說放棄本次時間片的執行權),例如呼叫yield()方法。

  2. 當前執行執行緒因為某些原因進入阻塞狀態,例如阻塞在I/O上。

  3. 當前執行執行緒結束,即執行完run()方法裡面的任務。

三種情況中第三種很好理解,任務執行完了自然放棄CPU,前兩種情況用兩個例子說明,先看使用yield放棄CPU什麼情況:

public class YeildThread {
 public static void main(String[] args) {
     MyThread mt = new MyThread();
     mt.start();
     while (true) {
         System.out.println("主執行緒");
     }
 }
}
class MyThread extends Thread {
 public void run() {
     while (true) {
         System.out.println("被放棄執行緒");
         Thread.currentThread().yield();
     }
 }
}
複製程式碼

擷取某段輸出如下,輸出“主執行緒”比“被放棄執行緒”執行的機會多,因為mt執行緒每次迴圈都把時間片讓給主執行緒,正是因為yield操作並不會永遠放棄CPU,僅僅只是放棄了此次時間片,把剩下的時間讓給別的執行緒,

主執行緒
主執行緒
主執行緒
主執行緒
主執行緒
主執行緒
被放棄執行緒
主執行緒
主執行緒
主執行緒
主執行緒
主執行緒
主執行緒
主執行緒
複製程式碼

第二個例子為節省程式碼量將使用虛擬碼表示,例子簡單但已能說明問題,執行程式將有兩條執行緒工作,ioThread每次遇到I/O阻塞就放棄當前的時間片,而主執行緒則按JVM分配的時間片正常執行。

public class IOBlockThread {
 public static void main(String[] args) {
     IOThread ioThread = new IOThread();
     ioThread.start();
     主執行緒任務執行
 }
}
class IOThread extends Thread {
 public void run() {
     while (true) {
         I/O阻塞
     }
 }
}
複製程式碼

Java的執行緒的排程機制都由JVM實現,假如有若干條執行緒,你想讓某些執行緒擁有更長的執行時間,或某些執行緒分配少點執行時間,這時就涉及“執行緒優先順序”,Java把執行緒優先順序分成10個級別,執行緒被建立時如果沒有明確宣告則使用預設優先順序,JVM將根據每個執行緒的優先順序分配執行時間的概率。有三個常量Thread.MIN_PRIORITY、Thread.NORM_PRIORITY、Thread.MAX_PRIORITY分別表示最小優先順序值(1)、預設優先順序值(5)、最大優先順序值(10)。

由於JVM的實現以宿主作業系統為基礎,所以Java優先順序值與各種不同作業系統的原生執行緒優先順序必然存在某種對映關係,這樣才足以封裝所有作業系統的優先順序提供統一優先順序語義。例如1-10優先順序值在linux可能要與0-99優先順序值進行對映,而windows系統則有7個優先順序要對映。

執行緒的排程策略決定上層多執行緒執行機制,JVM的執行緒排程器實現了搶佔式排程,每條執行緒執行的時間由它分配管理,它將按照執行緒優先順序的建議對執行緒執行的時間進行分配,優先順序越高,可能得到CPU的時間則越長。

-------------推薦閱讀------------

我的2017文章彙總——機器學習篇

我的2017文章彙總——Java及中介軟體

我的2017文章彙總——深度學習篇

我的2017文章彙總——JDK原始碼篇

我的2017文章彙總——自然語言處理篇

我的2017文章彙總——Java併發篇


跟我交流,向我提問:

這裡寫圖片描述

公眾號的選單已分為“分散式”、“機器學習”、“深度學習”、“NLP”、“Java深度”、“Java併發核心”、“JDK原始碼”、“Tomcat核心”等,可能有一款適合你的胃口。

為什麼寫《Tomcat核心設計剖析》

歡迎關注:

這裡寫圖片描述

相關文章