Executor框架簡介
Executor框架的兩級調度模型
Java多線程程序通常把應用分解為若干個任務扳缕,然后使用用戶級的調度器(Executor框架)將這些任務映射為固定數(shù)量的線程;在底層驴剔,操作系統(tǒng)內核將這些線程映射到硬件處理器上粥庄。被稱為兩級調度模型丧失。
Executor框架的結構與成員
- Executor框架的結構
Executor框架主要由3大部分組件組成:
- 任務: 包括被執(zhí)行任務需要實現(xiàn)的接口:Runnable接口或Callable接口
- 任務的執(zhí)行利花。包括任務執(zhí)行機制的核心接口Executor载佳,以及繼承自Executor的ExecutorService接口。Executor框架有兩個關鍵實現(xiàn)類實現(xiàn)了ExecutorService接口蔫慧,ThreadPoolExecutor和ScheduledThreadPoolExecutor
下面是這些類和接口的簡介: - Executor是一個接口,它是Executor框架的基礎睡扬,它將任務的提交與任務的執(zhí)行分離
- ThreadPoolExecutor是線程池的核心實現(xiàn)類,用來執(zhí)行被提交的任務
- ScheduledThreadPoolExecutor是一個實現(xiàn)類卖怜,可以在給定的延遲后運行命令,或者定期執(zhí)行命令奄抽。功能類似 于Timer甩鳄,但比Timer更靈活,功能更強大
- Future接口和實現(xiàn)Future接口的FutureTask類妙啃,代表異步計算的結果
Runnable接口和Callable接口的實現(xiàn)類,都可以被ThreadPoolExecutor或ScheduledThreadPoolExecutor執(zhí)行
ThreadPoolExector詳解
關于ThreadPoolExector的4個組件構成已經在java線程池實現(xiàn)原理中介紹過馆匿,在此不再重復储笑,下面介紹通過Exectors框架的工具類Exectors可以創(chuàng)建的3種類型的ThreadPoolExector:
- FixedThreadPool
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
FixedThreadPool的corePoolSize和maximumPoolSize都被設置為創(chuàng)建FixedThreadPool時指定的參數(shù)nThreads。
當線程池中的線程數(shù)大于corePoolSize時,keepAliveTime為多余的空閑線程等待新任務的最長時間盆昙,超過這個時間后多余的線程將被終止。這里把keepAliveTime設置為0L秕磷,意味著多余的空閑線程會被立即終止炼团。
FixedThreadPool使用無界隊列LinkedBlockingQueue作為線程池的工作隊列(隊列的容量為Integer.MAX_VALUE)。使用無界隊列作為工作隊列會對線程池帶來如下影響瘟芝。
- 當線程池中的線程數(shù)達到corePoolSize后,新任務將在無界隊列中等待晤郑,因此線程池中線程數(shù)不會超過corePoolSize。
- 由于1造寝,使用無界隊列時maximumPoolSize將是一個無效參數(shù)。
- 由于1和2析显,使用無界隊列時keepAliveTime將是一個無效參數(shù)签赃。
- 由于使用無界隊列,運行中的FixedThreadPool(未執(zhí)行shutDown()或shutDownNow())不會拒絕任務(不會調用RejectedExecutionHandler.rejectedExecution方法)
-
SingleThreadExecutor
SingleThreadExecutor是使用單個worker線程的Executor姊舵。
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
SingleThreadExecutor的corePoolSize和maximumPoolSize被設置為1.其他參數(shù)與FixedThreadPool相同括丁。所以SingleThreadExecutor使用無界隊列作為工作隊列對線程池帶來的影響與FixedThreadPool相同。
-
CachedThreadPool
CachedThreadPool是一個會根據(jù)需要創(chuàng)建新線程的線程池史飞。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
CachedThreadPool的corePoolSize被設置成0,即corePoolSize為空抽诉;maximumPoolSize被設置為Integer.MAX_VALUE吐绵,即maximumPool是無界的。這里把keepAliveTime設置為60L己单,意味著CachedThreadPool中的空閑線程等待任務的最長時間為60s,空閑線程超過60s后將會被終止纹份。
CachedThreadPool使用沒有沒有容量的SynchronousQueue作為線程池工作隊列廷痘,但CachedThreadPool的maximumPool是無界的。這意味著笋额,如果主線程提交任務的速度高于maximumPool中線程處理任務的速度時,CachedThreadPool就會不斷地創(chuàng)建新任務昨寞。極端情況下,CachedThreadPool會因為創(chuàng)建過多線程而耗盡CPU和內存資源援岩。
In The End
對比
corePoolSize | maximumPoolSize | workQueue | keepAliveTime | 特點 | |
---|---|---|---|---|---|
FixedThreadPool | nTread | nTread | LinkedBlockingQueue | 0 | 不會拒絕任務 |
SingleThreadExecutor | 1 | 1 | LinkedBlockingQueue | 0 | 只有單個worker線程 |
CachedThreadPool | 0 | Integer.MAX_VALUE | SynchronousQueue | 60 | 使用阻塞隊列享怀; maximumPoolSize無界 |
適用場景
FixedThreadPool:由于FixedThreadPool使用無界隊列,所以不會拒絕任務添瓷。因此合理設置corePoolSize數(shù)量配合任務隊列梅屉,適用于負載比較重的服務器鳞贷。
SingleThreadExecutor:SingleThreadExecutor只有一個worker線程,所以提交到SingleThreadExecutor的任務會保證順序的執(zhí)行惰聂,因此SingleThreadExecutor適用于需要保證順序的執(zhí)行任務咱筛,并且整個生命周期不會有多個線程的場景。
CachedThreadPool:CachedThreadPool時大小無界的線程池迅箩,因此適用于執(zhí)行很多短期異步任務的小程序饲趋,或者是負載較輕的服務器。