執行緒池原理–拒絕策略之RejectedExecutionHandler類
阿新 • • 發佈:2018-11-10
文章目錄
執行緒池原理–拒絕策略之RejectedExecutionHandler類
RejectedExecutionHandler介面用於定義當向執行緒池新增任務時,如果佇列已經滿了,該做如何處理。
ThreadPoolExecutor類中的相關方法
//RejectedExecutionHandler 屬性
private volatile RejectedExecutionHandler handler;
//提交任務
public void execute(Runnable command) {
if (command == null)
throw new NullPointerException();
int c = ctl.get();
if (workerCountOf(c) < corePoolSize) {
if ( addWorker(command, true))
return;
c = ctl.get();
}
if (isRunning(c) && workQueue.offer(command)) {
int recheck = ctl.get();
if (! isRunning(recheck) && remove(command))
reject(command);
else if (workerCountOf(recheck) == 0)
addWorker(null, false);
}
//新增任務失敗
else if (!addWorker(command, false))
//新增任務失敗的處理
reject(command);
}
}
//呼叫的是 RejectedExecutionHandler 類的 rejectedExecution方法()
final void reject(Runnable command) {
handler.rejectedExecution(command, this);
}
RejectedExecutionHandler 介面
public interface RejectedExecutionHandler {
void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}
RejectedExecutionHandler 介面有四個實現類,作為ThreadPoolExecutor類的內部類。
CallerRunsPolicy
如果執行緒池沒有Shutdown,則直接呼叫Runnable任務的run()方法。
public static class CallerRunsPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code CallerRunsPolicy}.
*/
public CallerRunsPolicy() { }
/**
* Executes task r in the caller's thread, unless the executor
* has been shut down, in which case the task is discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}
AbortPolicy
丟掉這個任務並丟擲 RejectedExecutionException異常。
public static class AbortPolicy implements RejectedExecutionHandler {
/**
* Creates an {@code AbortPolicy}.
*/
public AbortPolicy() { }
/**
* Always throws RejectedExecutionException.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
* @throws RejectedExecutionException always
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() +
" rejected from " +
e.toString());
}
}
DiscardPolicy
忽略這個任務,什麼也不做。
public static class DiscardPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardPolicy}.
*/
public DiscardPolicy() { }
/**
* Does nothing, which has the effect of discarding task r.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
}
}
DiscardOldestPolicy
這個策略從字面上也很好理解,丟棄最老的。也就是說如果佇列滿了,會將最早進入佇列的任務刪掉騰出空間,再嘗試加入佇列。
因為佇列是隊尾進,隊頭出,所以隊頭元素是最老的,因此每次都是移除對頭元素後再嘗試入隊.
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
/**
* Creates a {@code DiscardOldestPolicy} for the given executor.
*/
public DiscardOldestPolicy() { }
/**
* Obtains and ignores the next task that the executor
* would otherwise execute, if one is immediately available,
* and then retries execution of task r, unless the executor
* is shut down, in which case task r is instead discarded.
*
* @param r the runnable task requested to be executed
* @param e the executor attempting to execute this task
*/
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
//去除最早的任務
e.getQueue().poll();
//重新向佇列中新增該任務
e.execute(r);
}
}
}
自定義處理類
除了以上的四種,也可以自己實現RejectedExecutionHandler介面,需要實現rejectedExecution方法的邏輯。
並使用ThreadPoolExecutor物件的setRejectedExecutionHandler()方法設定值即可。
public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {
if (handler == null)
throw new NullPointerException();
this.handler = handler;
}