Executor兩級調度模型
在HotSpot虛擬機中,Java中的線程將會被一一映射爲操作系統的線程。
在Java虛擬機層面,用戶將多個任務提交給Executor框架,Executor負責分配線程執行它們;
在操作系統層面,操作系統再將這些線程分配給處理器執行。
Executor結構
Executor框架中的所有類可以分成三類:
- 任務
任務有兩種類型:Runnable和Callable。 -
任務執行器
Executor框架最核心的接口是Executor,它表示任務的執行器。
Executor的子接口爲ExecutorService。
ExecutorService有兩大實現類:ThreadPoolExecutor和ScheduledThreadPoolExecutor。 -
執行結果
Future接口表示異步的執行結果,它的實現類爲FutureTask。
線程池
Executors工廠類可以創建四種類型的線程池,通過Executors.newXXX即可創建。
1. FixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads){
return new ThreadPoolExecutor(nThreads,nThreads,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
- 1
- 2
- 3
- 它是一種固定大小的線程池;
- corePoolSize和maximunPoolSize都爲用戶設定的線程數量nThreads;
- keepAliveTime爲0,意味着一旦有多餘的空閒線程,就會被立即停止掉;但這裏keepAliveTime無效;
- 阻塞隊列採用了LinkedBlockingQueue,它是一個無界隊列;
- 由於阻塞隊列是一個無界隊列,因此永遠不可能拒絕任務;
- 由於採用了無界隊列,實際線程數量將永遠維持在nThreads,因此maximumPoolSize和keepAliveTime將無效。
2. CachedThreadPool
public static ExecutorService newCachedThreadPool(){
return new ThreadPoolExecutor(0,Integer.MAX_VALUE,60L,TimeUnit.MILLISECONDS,new SynchronousQueue<Runnable>());
}
- 1
- 2
- 3
- 它是一個可以無限擴大的線程池;
- 它比較適合處理執行時間比較小的任務;
- corePoolSize爲0,maximumPoolSize爲無限大,意味着線程數量可以無限大;
- keepAliveTime爲60S,意味着線程空閒時間超過60S就會被殺死;
- 採用SynchronousQueue裝等待的任務,這個阻塞隊列沒有存儲空間,這意味着只要有請求到來,就必須要找到一條工作線程處理他,如果當前沒有空閒的線程,那麼就會再創建一條新的線程。
3. SingleThreadExecutor
public static ExecutorService newSingleThreadExecutor(){
return new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
- 1
- 2
- 3
- 它只會創建一條工作線程處理任務;
- 採用的阻塞隊列爲LinkedBlockingQueue;
4. ScheduledThreadPool
它用來處理延時任務或定時任務。
-
它接收SchduledFutureTask類型的任務,有兩種提交任務的方式:
- scheduledAtFixedRate
- scheduledWithFixedDelay
-
SchduledFutureTask接收的參數:
- time:任務開始的時間
- sequenceNumber:任務的序號
- period:任務執行的時間間隔
-
它採用DelayQueue存儲等待的任務
- DelayQueue內部封裝了一個PriorityQueue,它會根據time的先後時間排序,若time相同則根據sequenceNumber排序;
- DelayQueue也是一個無界隊列;
-
工作線程的執行過程:
- 工作線程會從DelayQueue取已經到期的任務去執行;
- 執行結束後重新設置任務的到期時間,再次放回DelayQueue