Java线程池--拒绝策略RejectedExecutionHandler
當線程池的任務緩存隊列已滿并且線程池中的線程數目達到maximumPoolSize,如果還有任務到來就會采取任務拒絕策略,通常有以下四種策略:
當線程池的任務緩存隊列已滿并且線程池中的線程數目達到maximumPoolSize,如果還有任務到來就會采取任務拒絕策略,通常有以下四種策略:
ThreadPoolExecutor.AbortPolicy:丟棄任務并拋出RejectedExecutionException異常。 ThreadPoolExecutor.DiscardPolicy:也是丟棄任務,但是不拋出異常。 ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務,然后重新嘗試執行任務(重復此過程) ThreadPoolExecutor.CallerRunsPolicy:由調用線程處理該任務當Executor已經關閉(即執行了executorService.shutdown()方法后),并且Executor將有限邊界用于最大線程和工作隊列容量,且已經飽和時,在方法execute()中提交的新任務將被拒絕.
在以上述情況下,execute 方法將調用其 RejectedExecutionHandler 的RejectedExecutionHandler.rejectedExecution(java.lang.Runnable, java.util.concurrent.ThreadPoolExecutor) 方法。
線程池默認會采用的是defaultHandler策略。首先看defaultHandler的定義:
private static final RejectedExecutionHandler defaultHandler = new AbortPolicy(); // 使用默認的拒絕策略 //丟棄任務并拋出RejectedExecutionException異常。 public static class AbortPolicy implements RejectedExecutionHandler { public AbortPolicy() { } // 拋出異常 public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString()); } }如下是一個測試任務的例子,下面編寫4個測試用例來測試。
class MyRunnable implements Runnable { private String name; public MyRunnable(String name) { this.name = name; } @Override public void run() { try { System.out.println(this.name + " is running."); Thread.sleep(100); } catch (Exception e) { e.printStackTrace(); } } }看一下其他拒絕策略的具體實現。
- 1.DiscardPolicy 示例(也是丟棄任務,但是不拋出異常。)
線程池pool的”最大池大小”和”核心池大小”都為1(THREADS_SIZE),這意味著”線程池能同時運行的任務數量最大只能是1”。
線程池pool的阻塞隊列是ArrayBlockingQueue,ArrayBlockingQueue是一個有界的阻塞隊列,ArrayBlockingQueue的容量為1。這也意味著線程池的阻塞隊列只能有一個線程池阻塞等待。
根據”“中分析的execute()代碼可知:線程池中共運行了2個任務。第1個任務直接放到Worker中,通過線程去執行;第2個任務放到阻塞隊列中等待。其他的任務都被丟棄了!
- 2.DiscardOldestPolicy 示例(丟棄隊列最前面的任務,然后重新嘗試執行任務(重復此過程))
運行結果:
task-0 is running. task-9 is running.將”線程池的拒絕策略”由DiscardPolicy修改為DiscardOldestPolicy之后,當有任務添加到線程池被拒絕時,線程池會丟棄阻塞隊列中末尾的任務,然后將被拒絕的任務添加到末尾。
- 3.AbortPolicy 示例(丟棄任務并拋出RejectedExecutionException異常。)
(某一次)運行結果:
java.util.concurrent.RejectedExecutionExceptionat java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1774)at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:768)at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:656)at AbortPolicyDemo.main(AbortPolicyDemo.java:27) task-0 is running. task-1 is running.將”線程池的拒絕策略”由DiscardPolicy修改為AbortPolicy之后,當有任務添加到線程池被拒絕時,會拋出RejectedExecutionException。
- 4.CallerRunsPolicy 示例(由調用線程處理該任務)
(某一次)運行結果:
task-2 is running. task-3 is running. task-4 is running. task-5 is running. task-6 is running. task-7 is running. task-8 is running. task-9 is running. task-0 is running. task-1 is running.將”線程池的拒絕策略”由DiscardPolicy修改為CallerRunsPolicy之后,當有任務添加到線程池被拒絕時,線程池會將被拒絕的任務添加到”線程池正在運行的線程”中取運行。
參考來自http://blog.csdn.net/zhoufenqin/article/details/51012666
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Java线程池--拒绝策略RejectedExecutionHandler的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring Boot 2.x多线程--
- 下一篇: java美元兑换,(Java实现) 美元