1. 程式人生 > >執行緒池原理–拒絕策略之RejectedExecutionHandler類

執行緒池原理–拒絕策略之RejectedExecutionHandler類

文章目錄

執行緒池原理–總索引

執行緒池原理–拒絕策略之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;
    }