java多线程 ThreadPoolExecutor 策略的坑
? ?無論是使用jdk的線程池ThreadPoolExecutor 還是spring的線程池ThreadPoolTaskExecutor 都會(huì)使用到一個(gè)阻塞隊(duì)列來進(jìn)行存儲(chǔ)線程任務(wù)。
? ?當(dāng)線程不夠用時(shí),則將后續(xù)的任務(wù)暫存到 阻塞隊(duì)列中,等待有空閑線程來進(jìn)行。
? 當(dāng)這個(gè)阻塞隊(duì)列滿了的時(shí)候,會(huì)出現(xiàn)兩種情況
? ?正在運(yùn)行的線程數(shù)量小于 maximumPoolSize,那么還是要?jiǎng)?chuàng)建線程運(yùn)行這個(gè)任務(wù);
? ?正在運(yùn)行的線程數(shù)量大于或等于 maximumPoolSize,那么線程池會(huì)通過一個(gè)策略進(jìn)行對(duì)后續(xù)的任務(wù)進(jìn)行處理。
?
四種策略
ThreadPoolExecutor.AbortPolicy() ?拋出java.util.concurrent.RejectedExecutionException異常?
ThreadPoolExecutor.CallerRunsPolicy()?重試添加當(dāng)前的任務(wù),他會(huì)自動(dòng)重復(fù)調(diào)用execute()方法?
ThreadPoolExecutor.DiscardOldestPolicy()?拋棄舊的任務(wù)?
ThreadPoolExecutor.DiscardPolicy()?拋棄當(dāng)前的任務(wù)?
其他很容易看出來,最近踩了一個(gè)ThreadPoolExecutor.CallerRunsPolicy()的坑。
情景是這樣的:我需要通過線程進(jìn)行創(chuàng)建長(zhǎng)連接,當(dāng)開啟了15個(gè)線程的是,線程池最大即達(dá)到了maximumPoolSize的數(shù)量的時(shí)候,繼續(xù)增大請(qǐng)求量,會(huì)無緣無故的多出來
一個(gè)長(zhǎng)連接,由于有負(fù)載均衡,導(dǎo)致了很多請(qǐng)求無法從長(zhǎng)連接中得到。
經(jīng)過很長(zhǎng)時(shí)間的測(cè)試,最終發(fā)現(xiàn)了是ThreadPoolExecutor.CallerRunsPolicy()策略導(dǎo)致的。
這個(gè)測(cè)試是當(dāng)你的線程數(shù)達(dá)到最大,阻塞隊(duì)列也滿了的時(shí)候,之后的任務(wù)會(huì)強(qiáng)制先執(zhí)行,但是沒有了線程誰來執(zhí)行呢,這個(gè)策略會(huì)強(qiáng)制中斷主線程進(jìn)行執(zhí)行這個(gè)任務(wù)。
即是說,當(dāng)我的量上來,線程池不夠用的時(shí)候,中斷了我的主線程,主線程沒有長(zhǎng)連接,就建立了一個(gè)新的長(zhǎng)連接,那邊進(jìn)行了負(fù)載均衡,但是這邊不會(huì)在進(jìn)行主線程了,
導(dǎo)致很多請(qǐng)求接收不到。
假設(shè)隊(duì)列大小為 10,corePoolSize 為 3,maximumPoolSize 為 6,那么當(dāng)加入 20 個(gè)任務(wù)時(shí),執(zhí)行的順序就是這樣的:首先執(zhí)行任務(wù) 1、2、3,然后任務(wù) 4~13 被放入隊(duì)列。這時(shí)候隊(duì)列滿了,任務(wù) 14、15、16 會(huì)被馬上執(zhí)行,最終順序是:1、2、3、14、15、16、4、5、6、7、8、9、10、11、12、13。
?
踩坑完畢
最終做法:
換成ThreadPoolExecutor.DiscardPolicy()策略,還是從已經(jīng)建立的連接中進(jìn)行 的到請(qǐng)求,不要繼續(xù)創(chuàng)建連接。
?
轉(zhuǎn)載于:https://www.cnblogs.com/lic309/p/4564507.html
總結(jié)
以上是生活随笔為你收集整理的java多线程 ThreadPoolExecutor 策略的坑的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: OenLDAP 配置记录
- 下一篇: JavaScript 自定义对象