线程池的 RejectedExecutionHandler(拒绝策略)
轉(zhuǎn)載自??https://blog.csdn.net/jgteng/article/details/54411423
https://blog.csdn.net/luofenghan/article/details/78596950
JAVA為多線程場景提供了線程池,下面是一個線程池的構(gòu)造方法:
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), handler);}其中這些參數(shù)的使用和說明在我的一篇文章中已經(jīng)有了介紹,如果不太清楚的可以參考這篇文章:http://blog.csdn.net/jgteng/article/details/54409887
這里想對拒絕策略RejectedExecutionHandler做一下詳細(xì)的介紹。
在使用線程池并且使用有界隊(duì)列的時候,如果隊(duì)列滿了,任務(wù)添加到線程池的時候就會有問題,針對這些問題java線程池提供了以下幾種策略:
- AbortPolicy?(中止)?
- DiscardPolicy?(拋棄)?
- DiscardOldestPolicy? (拋棄最舊)?
- CallerRunsPolicy?(調(diào)用者運(yùn)行)
自定義
◇AbortPolicy
該策略是線程池的默認(rèn)策略。使用該策略時,如果線程池隊(duì)列滿了丟掉這個任務(wù)并且拋出RejectedExecutionException異常。
- 該策略是默認(rèn)的飽和策略;
- 會拋出未檢查的RejectedExecutionException,調(diào)用者可以捕獲這個異常,然后根據(jù)需求編寫自己的處理代碼;
源碼如下:
?public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {//不做任何處理,直接拋出異常throw new RejectedExecutionException("Task " + r.toString() +" rejected from " +e.toString());}◇DiscardPolicy
這個策略和AbortPolicy的slient版本,如果線程池隊(duì)列滿了,會直接丟掉這個任務(wù)并且不會有任何異常。
- 當(dāng)提交的任務(wù)無法保存到隊(duì)列中等待執(zhí)行時,Discard策略會悄悄拋棄該任務(wù)。
源碼如下:
? ?public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {//就是一個空的方法}◇DiscardOldestPolicy
- 會拋棄下一個將被執(zhí)行的任務(wù),然后嘗試重新提交的新任務(wù)。
- 如果工作隊(duì)列是一個優(yōu)先隊(duì)列,那么拋棄最舊的策略,會拋棄優(yōu)先級最高的任務(wù),因此最好不要將拋棄最舊的飽和策略和優(yōu)先級隊(duì)列放在一起使用。
源碼如下:
◇CallerRunsPolicy
- 該策略既不會拋棄任務(wù),也不會拋出異常,而是當(dāng)線程池中的所有線程都被占用后,并且工作隊(duì)列被填滿后,下一個任務(wù)會在調(diào)用execute時在主線程中執(zhí)行,從而降低新任務(wù)的流量。由于執(zhí)行任務(wù)需要一定的時間,因此主線程至少在一定的時間內(nèi)不能提交任何任務(wù),從而使得工作者線程有時間來處理正在執(zhí)行的任務(wù)。
- 另一方面,在這期間,主線程不會調(diào)用accept,那么到達(dá)的請求將被保存在TCP層的隊(duì)列中而不是在應(yīng)用程序的隊(duì)列中。如果持續(xù)過載,那么TCP層將最終發(fā)現(xiàn)他的請求隊(duì)列被填滿,因此同樣會開始拋棄請求。
- 當(dāng)服務(wù)器過載時,這種過載情況會逐漸向外蔓延開來——從線程池到工作隊(duì)列到應(yīng)用程序再到TCP層,最終到達(dá)客戶端,導(dǎo)致服務(wù)器在高負(fù)載的情況下實(shí)現(xiàn)一種平緩的性能降低。
源碼如下:
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
? ? ? ? ? ? if (!e.isShutdown()) {
? ? ? ? ? ? ? ? //直接執(zhí)行run方法
? ? ? ? ? ? ? ? r.run();
? ? ? ? ? ? }
? ? ? ? }
自定義
如果以上策略都不符合業(yè)務(wù)場景,那么可以自己定義一個拒絕策略,只要實(shí)現(xiàn)RejectedExecutionHandler接口,并且實(shí)現(xiàn)rejectedExecution方法就可以了。具體的邏輯就在rejectedExecution方法里去定義就OK了。
例如:我定義了我的一個拒絕策略,叫做MyRejectPolicy,里面的邏輯就是打印處理被拒絕的任務(wù)內(nèi)容
這幾種策略沒有好壞之分,只是適用不同場景,具體哪種合適根據(jù)具體場景和業(yè)務(wù)需要選擇,如果需要特殊處理就自己定義好了。
?
總結(jié)
以上是生活随笔為你收集整理的线程池的 RejectedExecutionHandler(拒绝策略)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中System.setPrope
- 下一篇: zookeeper是如何实现数据一致性的