ThreadPoolExecutor裡面4種拒絕策略
threadPoolExecutor類實現了ExecutorService介面和Executor介面,可以設定執行緒池corePoolSize,最大執行緒池大小,AliveTime,拒絕策略等。常用構造方法:
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize,
long keepAliveTime, TimeUnit unit,
BlockingQueue<Runnable> workQueue,
RejectedExecutionHandler handler)
corePoolSize: 執行緒池維護執行緒的最少數量
maximumPoolSize:執行緒池維護執行緒的最大數量
keepAliveTime: 執行緒池維護執行緒所允許的空閒時間
unit: 執行緒池維護執行緒所允許的空閒時間的單位
workQueue: 執行緒池所使用的緩衝佇列
handler: 執行緒池對拒絕任務的處理策略
當一個任務通過execute(Runnable)方法欲新增到執行緒池時:
l 如果此時執行緒池中的數量小於corePoolSize,即使執行緒池中的執行緒都處於空閒狀態,也要建立新的執行緒來處理被新增的任務。
2 如果此時執行緒池中的數量等於 corePoolSize,但是緩衝佇列 workQueue未滿,那麼任務被放入緩衝佇列。
3 如果此時執行緒池中的數量大於corePoolSize,緩衝佇列workQueue滿,並且執行緒池中的數量小於maximumPoolSize,建新的執行緒來處理被新增的任務。
4 如果此時執行緒池中的數量大於corePoolSize,緩衝佇列workQueue滿,並且執行緒池中的數量等於maximumPoolSize,那麼通過 handler所指定的策略來處理此任務。也就是:處理任務的優先順序為:核心執行緒corePoolSize、任務佇列workQueue、最大執行緒maximumPoolSize,如果三者都滿了,使用handler處理被拒絕的任務。
當執行緒池中的執行緒數量大於 corePoolSize時,如果某執行緒空閒時間超過keepAliveTime,執行緒將被終止。這樣,執行緒池可以動態的調整池中的執行緒數。
JDK內建了四種拒絕策略:
1、AbortPolicy策略
該策略直接丟擲異常,阻止系統工作
2、CallerRunsPolicy策略
只要執行緒池未關閉,該策略直接在呼叫者執行緒中運行當前被丟棄的任務。顯然這樣不會真的丟棄任務,但是,呼叫者執行緒效能可能急劇下降。
3、DiscardOledestPolicy策略
丟棄最老的一個請求任務,也就是丟棄一個即將被執行的任務,並嘗試再次提交當前任務。
4、DiscardPolicy策略
默默的丟棄無法處理的任務,不予任何處理。
擴充套件RejectedExecutioHandler介面,自定義拒絕策略
先看下RejectedExecutionHandler介面吧:
public interfaceRejectedExecutionHandler{
voidrejectedExecution(Runnable r,ThreadPoolExecutor executor);
}
再舉個例子吧:
public classTestRejectHandler {
class MyTask implements Runnable{
@Override
public void run() {
System.out.println("Thread ID:"+Thread.currentThread().getId());
try{
Thread.sleep(1000);
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
public void test(){
ThreadPoolExecutor executor= newThreadPoolExecutor(5, 5,
0L, TimeUnit.MILLISECONDS,
newLinkedBlockingQueue(10),
Executors.defaultThreadFactory(),
newRejectedExecutionHandler() {
@Override
public voidrejectedExecution(Runnable r, ThreadPoolExecutor executor) {
System.out.println(r.toString()+" 被拋棄了");
}
});
MyTask task= newMyTask();
for(int i=0;i<20;i++){
executor.submit(task);
}
executor.shutdown();
}
}