日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

线程池的 RejectedExecutionHandler(拒绝策略)

發布時間:2024/2/28 编程问答 42 豆豆
生活随笔 收集整理的這篇文章主要介紹了 线程池的 RejectedExecutionHandler(拒绝策略) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉載自??https://blog.csdn.net/jgteng/article/details/54411423

https://blog.csdn.net/luofenghan/article/details/78596950

JAVA為多線程場景提供了線程池,下面是一個線程池的構造方法:

public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,RejectedExecutionHandler handler) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), handler);}

其中這些參數的使用和說明在我的一篇文章中已經有了介紹,如果不太清楚的可以參考這篇文章:http://blog.csdn.net/jgteng/article/details/54409887
這里想對拒絕策略RejectedExecutionHandler做一下詳細的介紹。

在使用線程池并且使用有界隊列的時候,如果隊列滿了,任務添加到線程池的時候就會有問題,針對這些問題java線程池提供了以下幾種策略:

  • AbortPolicy?(中止)?
  • DiscardPolicy?(拋棄)?
  • DiscardOldestPolicy? (拋棄最舊)?
  • CallerRunsPolicy?(調用者運行)

自定義

AbortPolicy
該策略是線程池的默認策略。使用該策略時,如果線程池隊列滿了丟掉這個任務并且拋出RejectedExecutionException異常。

  • 該策略是默認的飽和策略;
  • 會拋出未檢查的RejectedExecutionException,調用者可以捕獲這個異常,然后根據需求編寫自己的處理代碼;

源碼如下:

?public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {//不做任何處理,直接拋出異常throw new RejectedExecutionException("Task " + r.toString() +" rejected from " +e.toString());}

DiscardPolicy
這個策略和AbortPolicy的slient版本,如果線程池隊列滿了,會直接丟掉這個任務并且不會有任何異常。

  • 當提交的任務無法保存到隊列中等待執行時,Discard策略會悄悄拋棄該任務。

源碼如下:

? ?public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {//就是一個空的方法}

DiscardOldestPolicy

  • 會拋棄下一個將被執行的任務,然后嘗試重新提交的新任務。
  • 如果工作隊列是一個優先隊列,那么拋棄最舊的策略,會拋棄優先級最高的任務,因此最好不要將拋棄最舊的飽和策略和優先級隊列放在一起使用。


源碼如下:

? ? ? ? public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {if (!e.isShutdown()) {//移除隊頭元素e.getQueue().poll();//再嘗試入隊e.execute(r);}}

CallerRunsPolicy

  • 該策略既不會拋棄任務,也不會拋出異常,而是當線程池中的所有線程都被占用后,并且工作隊列被填滿后,下一個任務會在調用execute時在主線程中執行,從而降低新任務的流量。由于執行任務需要一定的時間,因此主線程至少在一定的時間內不能提交任何任務,從而使得工作者線程有時間來處理正在執行的任務。
  • 另一方面,在這期間,主線程不會調用accept,那么到達的請求將被保存在TCP層的隊列中而不是在應用程序的隊列中。如果持續過載,那么TCP層將最終發現他的請求隊列被填滿,因此同樣會開始拋棄請求。
  • 當服務器過載時,這種過載情況會逐漸向外蔓延開來——從線程池到工作隊列到應用程序再到TCP層,最終到達客戶端,導致服務器在高負載的情況下實現一種平緩的性能降低。


源碼如下:
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
? ? ? ? ? ? if (!e.isShutdown()) {
? ? ? ? ? ? ? ? //直接執行run方法
? ? ? ? ? ? ? ? r.run();
? ? ? ? ? ? }
? ? ? ? }

自定義
如果以上策略都不符合業務場景,那么可以自己定義一個拒絕策略,只要實現RejectedExecutionHandler接口,并且實現rejectedExecution方法就可以了。具體的邏輯就在rejectedExecution方法里去定義就OK了。
例如:我定義了我的一個拒絕策略,叫做MyRejectPolicy,里面的邏輯就是打印處理被拒絕的任務內容

public class MyRejectPolicy implements RejectedExecutionHandler{public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {//Sender是我的Runnable類,里面有message字段if (r instanceof Sender) {Sender sender = (Sender) r;//直接打印System.out.println(sender.getMessage());}} }

這幾種策略沒有好壞之分,只是適用不同場景,具體哪種合適根據具體場景和業務需要選擇,如果需要特殊處理就自己定義好了。

?

總結

以上是生活随笔為你收集整理的线程池的 RejectedExecutionHandler(拒绝策略)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。