线程池原理–拒绝策略之RejectedExecutionHandler类

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u011676300/article/details/83046017

线程池原理–总索引

线程池原理–拒绝策略之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()方法设置值即可。

扫描二维码关注公众号,回复: 3629764 查看本文章
public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {
        if (handler == null)
            throw new NullPointerException();
        this.handler = handler;
    }

猜你喜欢

转载自blog.csdn.net/u011676300/article/details/83046017