Java線程池的使用及工作原理
點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”
優(yōu)質(zhì)文章,第一時(shí)間送達(dá)
前言
在日常開發(fā)過程中總是以單線程的思維去編碼,沒有考慮到在多線程狀態(tài)下的運(yùn)行狀況。由此引發(fā)的結(jié)果就是請(qǐng)求過多,應(yīng)用無(wú)法響應(yīng)。為了解決請(qǐng)求過多的問題,又衍生出了線程池的概念。通過“池”的思想,從而合理的處理請(qǐng)求。本文記錄了Java中線程池的使用及工作原理,如有錯(cuò)誤,歡迎指正。
什么是線程池?
線程池要解決什么問題?
說(shuō)到線程池就一定要從線程的生命周期講起。

從圖中可以了解無(wú)論任務(wù)執(zhí)行多久,每個(gè)線程都要經(jīng)歷從生到死的狀態(tài)。而使用線程池就是為了避免線程的重復(fù)創(chuàng)建,從而節(jié)省了線程的New至Runnable, Running至Terminated的時(shí)間;同時(shí)也會(huì)復(fù)用線程,最小化的節(jié)省系統(tǒng)資源,于此同時(shí)提高了響應(yīng)速度。
線程池的使用
線程池的創(chuàng)建
使用ThreadPoolExecutor并配置7個(gè)參數(shù)完成線程池的創(chuàng)建
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
corePoolSize:線程池中核心線程的最大值
maximumPoolSize:線程池中最大線程數(shù)
keepAliveTime:非核心線程空閑的存活時(shí)間大小
unit:keepAliveTime的單位,常用的有秒、分鐘、小時(shí)等
workQueue:阻塞隊(duì)列類型
threadFactory:線程工廠,用于配置線程的名稱,是否為守護(hù)線程等
handler:線程池的拒絕策略
常用阻塞隊(duì)列
ArrayBlockingQueue
底層基于數(shù)組的實(shí)現(xiàn)的有界阻塞隊(duì)列
LinkedBlockingQueue
底層基于單鏈表的阻塞隊(duì)列,可配置容量,不配置容量默認(rèn)為Integer.MAX_VALUE
線程工廠
在《阿里巴巴Java開發(fā)手冊(cè)》中強(qiáng)制要求指定線程的名稱
由于工作是使用hutool比較多,里面也包含對(duì)ThreadFactory的封裝,可以很方便的指定名稱
ThreadFactory threadFactory = ThreadFactoryBuilder.create().setNamePrefix("myThread-").build();
拒絕策略
當(dāng)線程池內(nèi)工作線程數(shù)大于maximumPoolSize時(shí),線程就不再接受任務(wù),執(zhí)行對(duì)應(yīng)的拒絕策略;目前支持的拒絕策略有四種:
AbortPolicy(默認(rèn)):丟棄任務(wù)并拋出
RejectedExecutionException異常CallerRunsPolicy:由調(diào)用者處理
DiscardOldestPolicy:丟棄隊(duì)列中最前面的任務(wù),并重新入隊(duì)列
DiscardPolicy:丟棄任務(wù)但不拋出異常
線程池的執(zhí)行邏輯
// 創(chuàng)建線程工廠
ThreadFactory threadFactory = ThreadFactoryBuilder.create().setNamePrefix("myThread-").build();
// 創(chuàng)建線程池
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(100), threadFactory, new ThreadPoolExecutor.AbortPolicy());
execute()方法
// 組合值;保存了線程池的工作狀態(tài)和工作線程數(shù)
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
public void execute(Runnable command) {
// 任務(wù)為空 拋出NPE
if (command == null)
throw new NullPointerException();
// 獲取線程池狀態(tài)
int c = ctl.get();
// 如果工作線程數(shù)小于核心線程數(shù)就創(chuàng)建新線程
if (workerCountOf(c) < corePoolSize) {
if (addWorker(command, true))
return;
c = ctl.get();
}
// 如果線程池處于Running狀態(tài),就把任務(wù)放在隊(duì)列尾部
if (isRunning(c) && workQueue.offer(command)) {
// 重新檢查線程池狀態(tài)
int recheck = ctl.get();
// 如果線程池不是Running狀態(tài),就移除剛才添加的任務(wù),并執(zhí)行拒絕策略
if (! isRunning(recheck) && remove(command))
reject(command);
// 是Running狀態(tài),就添加線程
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
// 添加任務(wù)失敗,執(zhí)行拒絕策略
else if (!addWorker(command, false))
reject(command);
}
// addWorker()完成線程的創(chuàng)建
執(zhí)行流程

版權(quán)聲明:本文為博主原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明。
本文鏈接:
https://blog.csdn.net/lhc_makefunny/article/details/117308066
