線程池技術(shù)在并發(fā)時(shí)經(jīng)常會(huì)使用到,java中的線程池的使用是通過調(diào)用ThreadPoolExecutor來實(shí)現(xiàn)的。ThreadPoolExecutor提供了四個(gè)構(gòu)造函數(shù),最后都會(huì)歸結(jié)于下面這個(gè)構(gòu)造方法:
// 七個(gè)參數(shù)的構(gòu)造函數(shù) public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler)
這些參數(shù)的意義如下:
- corePoolSize:該線程池中核心線程數(shù)最大值
- maximumPoolSize: 該線程池中線程總數(shù)最大值
- keepAliveTime:該線程池中非核心線程閑置超時(shí)時(shí)長(zhǎng)
- unit:keepAliveTime的單位
- workQueue:阻塞隊(duì)列BlockingQueue,維護(hù)著等待執(zhí)行的Runnable對(duì)象
- threadFactory:創(chuàng)建線程的接口,需要實(shí)現(xiàn)他的Thread newThread(Runnable r)方法。
- RejectedExecutionHandler:飽和策略,最大線程和工作隊(duì)列容量且已經(jīng)飽和時(shí)execute方法都將調(diào)用RejectedExecutionHandler 。
ThreadPoolExecutor工作流程
流程圖如下:
大致過程陳述為:
- 向線程池中添加任務(wù),當(dāng)任務(wù)數(shù)量少于corePoolSize時(shí),會(huì)自動(dòng)創(chuàng)建thead來處理這些任務(wù);
- 當(dāng)添加任務(wù)數(shù)大于corePoolSize且少于maximmPoolSize時(shí),不在創(chuàng)建線程,而是將這些任務(wù)放到阻塞隊(duì)列中,等待被執(zhí)行;
- 接上面2的條件,且當(dāng)阻塞隊(duì)列滿了之后,繼續(xù)創(chuàng)建thread,從而加速處理阻塞隊(duì)列;
- 當(dāng)添加任務(wù)大于maximmPoolSize時(shí),根據(jù)飽和策略決定是否容許繼續(xù)向線程池中添加任務(wù),默認(rèn)的飽和策略是AbortPolicy(直接丟棄)。
線程池中使用的阻塞隊(duì)列
- ArrayBlockingQueue:基于數(shù)組結(jié)構(gòu)的有界阻塞隊(duì)列,構(gòu)造函數(shù)一定要傳大小,F(xiàn)IFO(先進(jìn)先出);
- LinkedBlockingQueue:無界,默認(rèn)大小65536(Integer.MAX_VALUE),當(dāng)大量請(qǐng)求任務(wù)時(shí),容易造成內(nèi)存耗盡。
- SynchronousQueue:同步隊(duì)列,是一個(gè)特殊的BlockingQueue,它沒有容量(這是因?yàn)樵赟ynchronousQueue中,插入將等待另一個(gè)線程的刪除操作,反之亦然)。具體可以參考:《Java SynchronousQueue Examples(譯)》
- PriorityBlockingQueue: 優(yōu)先隊(duì)列,無界。
- DelayedWorkQueue:這個(gè)隊(duì)列接收到任務(wù)時(shí),首先先入隊(duì),只有達(dá)到了指定的延時(shí)時(shí)間,才會(huì)執(zhí)行任務(wù)
阻塞隊(duì)列常見的方法如下表所示:
方法名 | 說明 | 注意 |
---|---|---|
add | 增加一個(gè)元索 | 如果隊(duì)列已滿,則拋出一個(gè)IIIegaISlabEepeplian異常 |
remove | 移除并返回隊(duì)列頭部的元素 | 如果隊(duì)列為空,則拋出一個(gè)NoSuchElementException異常 |
element | 返回隊(duì)列頭部的元素 | 如果隊(duì)列為空,則拋出一個(gè)NoSuchElementException異常 |
offer | 添加一個(gè)元素并返回true | 如果隊(duì)列已滿,則返回false |
poll | 移除并返問隊(duì)列頭部的元素 | 如果隊(duì)列為空,則返回null |
peek | 返回隊(duì)列頭部的元素 | 如果隊(duì)列為空,則返回null |
put | 添加一個(gè)元素 | 如果隊(duì)列滿,則阻塞 |
take | 移除并返回隊(duì)列頭部的元素 | 如果隊(duì)列為空,則阻塞 |
常見四種線程池
- newCachedThreadPool
- newFixedThreadPool
- newSingleThreadExecutor
- newScheduledThreadPool
線程池 | 使用的阻塞隊(duì)列 | 線程池大小 | 超時(shí) |
---|---|---|---|
CachedThreadPool | SynchronousQueue(隊(duì)列長(zhǎng)度無限 | 可增加,最大值Integer.MAX_VALUE | 默認(rèn)60秒超時(shí) |
FixedThreadPool | LinkedBlockingQueue(隊(duì)列長(zhǎng)度無限) | 可指定nThreads,固定數(shù)量 | 不會(huì)超時(shí) |
newSingleThreadExecutor | LinkedBlockingQueue(隊(duì)列長(zhǎng)度無限), | 固定為1 | 不超時(shí) |
newScheduledThreadPool | DelayedWorkQueue | 可增加,最大值Integer.MAX_VALUE | 不超時(shí) |
它們通過Executors以靜態(tài)方法的方式直接調(diào)用,實(shí)質(zhì)上是它們最終調(diào)用的是ThreadPoolExecutor的構(gòu)造方法,也就是本文最前面那段代碼。
注:KeepAliveTime=0的話,表示不等待
《阿里巴巴java開發(fā)手冊(cè)》中建議線程池不使用 Executors 去創(chuàng)建,而是通過 ThreadPoolExecutor的方式,這樣的處理方式讓寫的人員更加明確線程池的運(yùn)行規(guī)則,規(guī)避資源耗盡的風(fēng)險(xiǎn)。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。