Java 四種常見執行緒池解析
四種常見執行緒池
執行緒池用於管理執行緒的建立與銷燬,避免無用執行緒造成資源浪費,當需要建立多個執行緒時,我們往往需要一個管理者來管理這些執行緒,這也就引入了執行緒池的概念.Android中有四種較為常見的執行緒池也是我們使用最廣泛的執行緒池,FixedThreadPool(固定執行緒數的執行緒池),ChachedThreadPool(快取型執行緒池),SingleThreadExecutor(單執行緒執行緒池),ScheduledThreadPool(週期性排程執行緒池).這幾種執行緒池本質都是通過ThreadPoolExecutor來建立的.當然在使用中我們只需要通過Executors就能快速建立這幾類執行緒池,但是我們需要理解其建立的具體流程.
執行緒池工作流程
ThreadPoolExecutor
這四種常見執行緒池建立的本質都是通過ThreadPoolExecutor來建立的,只是傳入的引數不同就生成了不同的執行緒池,所以我們需要學習ThreadPoolExecutor的構造方法,這樣我們就可以創建出符合我們需求的執行緒池了.
ThreadPoolExecutor的重要屬性
- corePoolSize:核心執行緒數,預設情況執行緒池為空,只有在提交任務後,才會建立新的執行緒去執行任務,當正在執行的執行緒數少於核心執行緒數時,則建立新執行緒來執行任務;如果等於或者多於核心執行緒數,則不再建立.如果使用prestartAllcoreThread方法,則會提前建立執行緒填滿執行緒池,等待任務.
- maximumPoolSize:執行緒池允許建立的最大執行緒數(包括核心執行緒與非核心執行緒),如果任務佇列已經滿了,但是小於maximumPoolSize,仍然可以建立非核心執行緒來執行任務.
- keepAliveTime:非核心執行緒的閒置時間,非核心執行緒一旦存活時間超過keepAliveTime則會被回收,如果有很多重複任務則可以提高keepAliveTime來保證執行緒的重複利用率,如果設定了allowCoreThreadTimeOut屬性為true.
- TimeUtil:keepAliveTime的單位,包含天,時,分,秒,毫秒等.
- WorkQueue:任務佇列,這是一個阻塞佇列.
- ThreadFactory:執行緒工廠,通過執行緒工廠可以為執行緒取名,一般無需使用.
- RejectedExecutionHandler:飽和策略,當任務和執行緒池都滿了時採用的處理方法,預設為AbordPolicy策略表示無法處理新任務.
飽和策略
飽和策略就是當任務佇列和執行緒池都已經滿了的時候,有新任務進來時採用何種策略來處理新任務.
- AbordPolicy:表示無法處理新任務
- CallerRunsPolicy:通過呼叫者所線上程處理新任務.
- DiscardPolicy:無法執行新任務,並刪除該任務
- DiscardOldestPolicy:丟棄佇列最近的任務並執行該任務.
FixedThreadPool
FixedThreadPool的核心執行緒數和最大執行緒數都指定為同一值也就意味著,該執行緒池中只包含了核心執行緒,並且核心執行緒數量已經規定好了,其傳入的keepAliveTime為0L表示,一旦任務執行完畢,執行緒空閒就會立即被回收.其傳入的任務佇列為LinkedBlockingQueue(無界阻塞佇列即任務數量沒有限制),如果執行緒多於核心執行緒數時,任務會被放入任務佇列中,等待能建立新執行緒時再執行.
使用中我們通過Excutors來建立FixedThreadPool
Executors.newFixedThreadPool();
FixedThreadPool建立原始碼
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
ChachedThreadPool
ChachedThreadPool執行緒池中核心執行緒數為0,其最大執行緒數為Integer.MAX_VALUE(即無界),這也意味著所有執行緒都為非核心執行緒,任務佇列為SynchronousQueue(阻塞佇列),當任務執行完畢後執行緒可以存活60秒來等待任務匹配,如果沒有任務則被銷燬,如果匹配上了任務,則提高了執行緒的重複利用率.該執行緒池適用於大量需要立即執行的任務且任務週期較短的任務.
使用中我們通過Excutors來建立ChachedThreadPool
Executors.newCachedThreadPool();
ChachedThreadPool建立原始碼
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
SingleThreadExecutor
單執行緒池,該執行緒池中只存在一個核心執行緒,任務佇列為LinkedBlockingQueue,即該執行緒池會把任務放入該無界阻塞佇列中一個一個執行.
使用中我們通過Excutors來建立SingleThreadExecutor
Executors.newSingleThreadExecutor();
SingleThreadExecutor建立原始碼
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
ScheduledThreadPool
定時排程執行緒,該執行緒可以實現延時和週期性迴圈任務.具有固定的核心執行緒數以及無界的非核心執行緒數,任務佇列為DelayedWorkQueue(延時佇列),DelayedWorkQueue佇列會將任務按照順序排列,將先執行的任務放在佇列前端.
使用中我們通過Excutors來建立ScheduledThreadPool
Executors.newScheduledThreadPool();
ScheduledThreadPool建立原始碼
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) {
return new ScheduledThreadPoolExecutor(corePoolSize);
}
ScheduledThreadPoolExecutor的構造方法 這裡呼叫了其super方法,其父類就是ThreadPoolExecutor,所以本質上ScheduledThreadPool也是通過ThreadPoolExecutor建立的.但是有一點不同ScheduledThreadPool的管理佇列是一個延時佇列,所以它可以定時排程執行緒.
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE,
DEFAULT_KEEPALIVE_MILLIS, MILLISECONDS,
new DelayedWorkQueue());
}