ThreadPoolExecutor 用于創(chuàng)建線程池荧飞,它有 4 個重載構(gòu)造器,我們以最多參數(shù)的構(gòu)造器講解:
ThreadPoolExecutor(int corePoolSize, # 線程池核心線程個數(shù)豺型,默認線程池線程個數(shù)為 0,只有接到任務(wù)才新建線程
int maximumPoolSize, # 線程池最大線程數(shù)量
long keepAliveTime, # 線程池空閑時绑咱,線程存活的時間爵嗅,當(dāng)線程池中的線程數(shù)大于 corePoolSize 時才會起作用
TimeUnit unit, # 時間單位
BlockingQueue<Runnable> workQueue, # 阻塞隊列,當(dāng)達到線程數(shù)達到 corePoolSize 時疲恢,將任務(wù)放入隊列等待線程處理
ThreadFactory threadFactory, # 線程工廠
RejectedExecutionHandler handler) # 線程拒絕策略凶朗,當(dāng)隊列滿了并且線程個數(shù)達到 maximumPoolSize 后采取的策略
阻塞隊列有以下 4 種:
ArrayBlockingQueue:基于數(shù)組、有界显拳,按 FIFO(先進先出)原則對元素進行排序棚愤;
LinkedBlockingQueue:基于鏈表,按FIFO (先進先出) 排序元素杂数,吞吐量通常要高于 ArrayBlockingQueue宛畦;
SynchronousQueue:每個插入操作必須等到另一個線程調(diào)用移除操作,否則插入操作一直處于阻塞狀態(tài)揍移,吞吐量通常要高于 LinkedBlockingQueue次和;
PriorityBlockingQueue:具有優(yōu)先級的、無限阻塞隊列羊精。
線程拒絕策略有以下 4 種:
CallerRunsPolicy:如果發(fā)現(xiàn)線程池還在運行斯够,就直接運行這個線程;
DiscardOldestPolicy:在線程池的等待隊列中,將頭取出一個拋棄喧锦,然后將當(dāng)前線程放進去;
DiscardPolicy:默默丟棄,不拋出異常;
AbortPolicy:java默認读规,拋出一個異常(RejectedExecutionException)。
實現(xiàn)原則:
如果當(dāng)前池大小 poolSize 小于 corePoolSize 燃少,則創(chuàng)建新線程執(zhí)行任務(wù)束亏;
如果當(dāng)前池大小 poolSize 大于 corePoolSize ,且等待隊列未滿阵具,則進入等待隊列碍遍;
如果當(dāng)前池大小 poolSize 大于 corePoolSize 且小于 maximumPoolSize 定铜,且等待隊列已滿,則創(chuàng)建新線程執(zhí)行任務(wù)怕敬;
如果當(dāng)前池大小 poolSize 大于 corePoolSize 且大于 maximumPoolSize 揣炕,且等待隊列已滿,則調(diào)用拒絕策略來處理該任務(wù)东跪;
線程池里的每個線程執(zhí)行完任務(wù)后不會立刻退出畸陡,而是會去檢查下等待隊列里是否還有線程任務(wù)需要執(zhí)行,如果在 keepAliveTime 里等不到新的任務(wù)了虽填,那么線程就會退出丁恭。
2.2.3 內(nèi)置線程池
在 java.util.concurrent 包中已經(jīng)提供為大多數(shù)使用場景的內(nèi)置線程池:
Executors.newSingleThreadExecutor() # 單條線程
Executors.newFixedThreadPool(int n) # 固定數(shù)目線程的線程池
Executors.newCachedThreadPool() # 創(chuàng)建一個可緩存的線程池,調(diào)用execute 將重用以前構(gòu)造的線程(如果線程可用)斋日。如果現(xiàn)有線程沒有可用的牲览,則創(chuàng)建一個新線程并添加到池中。終止并從緩存中移除那些已有 60 秒鐘未被使用的線程恶守。
Executors.newScheduledThreadPool(int n) # 支持定時及周期性的任務(wù)執(zhí)行的線程池第献,多數(shù)情況下可用來替代 Timer 類。
上述 4 種線程池底層都是通過創(chuàng)建 ThreadPoolExecutor 獲取線程池熬的。
newSingleThreadExecutor
主要用于串行(順序執(zhí)行)操作場景痊硕。newFixedThreadPool
主要用于負載比較重的場景,為了資源的合理利用押框,需要限制當(dāng)前線程數(shù)量岔绸。newCachedThreadPool
主要用于并發(fā)執(zhí)行大量短期的小任務(wù),或者是負載較輕的服務(wù)器橡伞。newScheduledThreadPool
ScheduledExecutorService 繼承 ThreadPoolExecutor盒揉。
2.2.4 提交任務(wù)
獲取 ExecutorService 對象后,我們需要提交任務(wù)來讓線程池中的線程執(zhí)行兑徘,提交任務(wù)的方法有 2 種:
# void execute():提交不需要返回值的任務(wù)
pool.execute(() -> System.out.println("1L"));
# Future<T> submit(): 提交需要返回值的任務(wù)
Future<Long> future = pool.submit(() -> {
System.out.println("1L");
return 1L;
});
Long result = future.get();