對於核心的幾個線程池
newSingleThreadExecutor
newFixedThreadPool
newCachedThreadPool
其內部都是使用的ThreadPoolExecutor實現的,下面給出它們的實現方式:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
我們再來看看ThreadPoolExecutor的構造方法
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
}
參數說明:
corePoolSize:線程池中線程的數量
maximumPoolSize:線程池中最大的線程的數量
keepAliveTime:當線程池中線程的數量超過maximumPoolSize時,多餘的空閒的線程的存活時間
unit:keepAliveTime的單位
workQueue:任務隊列,存放已經提交但尚未被執行的任務
threadFactory:產生現成的工廠
handler:當任務太多來不及執行的時候的拒絕策略
重點介紹workQueue,它是一個BlockingQueue的接口的對象,根據隊列的功能分類,可以使用下面幾種BlockingQueue的實現:
1. SynchronousQueue,其沒有容量,沒進行一次put都必須等待一個相應的take,反之亦然,提交的任務不會被真實的保存,而總是將新任務提交給線程執行,如果沒有空閒的線程並且線程數量還沒有達到maximumPoolSize,則嘗試創建新的線程,如果已經達到最大的線程數,那麼就會執行拒絕策略
2. ArrayBlockingQueue,ArrayBlockingQueue必須包含一個參數,用於表示該隊列的最大的容量,如果線程池的數量小於corePoolSize,那麼提交任務後就會創建新的線程用於執行任務,如果線程池的數量大於corePoolSize,那麼就會將任務假如等待隊列ArrayBlockingQueue中,如果隊列滿了的話,線程池中線程的數量也沒有達到maximumPoolSize,那麼會創建新的線程執行任務,若大於了maxmium,那麼就會執行拒絕策略。由此可見,ArrayBlockingQueue只有在隊列滿了的情況下,線程池中的線程數量纔會突破corePoolSize個。
3. LinkedBlockingQueue,與有界隊列ArrayBlockingQueue不一樣的,除非系統資源耗盡,否則無界隊列不存在任務入隊失敗的情況,當有新的任務進來的時候,如果線程池中線程的數量不足corePoolSize,那麼會創建新的線程執行任務,但是當線程池中的線程的數量達到corePoolSize的時候,則任務就會直接進入到LinkedBlockingQueue中
在此,我們就不難發現爲什麼newFixedThreadPool實現的時候使用的是LinkedBlockingQueue,而newCachedThreadPool實現的時候使用的是SynchronousQueue。
拒絕策略
JDK內置的拒絕策略如下:
AbortPolicy:直接拋出異常
CallerRunsPolicy:直接在調用者的線程中,運行當前被丟棄的任務
DiscardOledestPolicy:丟棄掉最老的一個任務
DiscardPolicy:默默地丟棄無法處理的任務,不予任何處理
拒絕策略的源代碼如下所示:
public static class AbortPolicy implements RejectedExecutionHandler {
public AbortPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
public static class CallerRunsPolicy implements RejectedExecutionHandler {
public CallerRunsPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
public DiscardOldestPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll();
e.execute(r);
}
}
}
public static class DiscardPolicy implements RejectedExecutionHandler {
public DiscardPolicy() { }
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}