Java併發程式設計的藝術(十一)——執行緒池(2)
阿新 • • 發佈:2019-02-01
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>());
}
- 它是一種固定大小的執行緒池;
- 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>());
}
- 它是一個可以無限擴大的執行緒池;
- 它比較適合處理執行時間比較小的任務;
- corePoolSize為0,maximumPoolSize為無限大,意味著執行緒數量可以無限大;
- keepAliveTime為60S,意味著執行緒空閒時間超過60S就會被殺死;
- 採用SynchronousQueue裝等待的任務,這個阻塞佇列沒有儲存空間,這意味著只要有請求到來,就必須要找到一條工作執行緒處理他,如果當前沒有空閒的執行緒,那麼就會再建立一條新的執行緒。
3. SingleThreadExecutor
public static ExecutorService newSingleThreadExecutor(){
return new ThreadPoolExecutor(1,1,0L,TimeUnit.MILLISECONDS,new LinkedBlockingQueue<Runnable>());
}
- 它只會建立一條工作執行緒處理任務;
- 採用的阻塞佇列為LinkedBlockingQueue;
4. ScheduledThreadPool
它用來處理延時任務或定時任務。
它接收SchduledFutureTask型別的任務,有兩種提交任務的方式:
- scheduledAtFixedRate
- scheduledWithFixedDelay
SchduledFutureTask接收的引數:
- time:任務開始的時間
- sequenceNumber:任務的序號
- period:任務執行的時間間隔
它採用DelayQueue儲存等待的任務
- DelayQueue內部封裝了一個PriorityQueue,它會根據time的先後時間排序,若time相同則根據sequenceNumber排序;
- DelayQueue也是一個無界佇列;
工作執行緒的執行過程:
- 工作執行緒會從DelayQueue取已經到期的任務去執行;
- 執行結束後重新設定任務的到期時間,再次放回DelayQueue