Bootstrap

Java线程池中的拒绝策略


一、什么是线程池中的拒绝策略?

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)

1、谈拒绝策略前,需要先说一下Java中的线程池ThreadPoolExecutor,对于Java中线程池的使用一般都是通过new ThreadPoolExecutor来创建,而通过其构造方法可以发现对于其创建需要7个参数:

在这里插入代码片

 1. int corePoolSize -----------------------------------核心线程数
 2. int maximumPoolSize---------------------------------最大线程数
 3. long keepAliveTime----------------------------------时间大小
 4. TimeUnit unit---------------------------------------时间类型
 5. BlockingQueue<Runnable> workQueue-------------------任务队列
 6. ThreadFactory threadFactory-------------------------创建线程的工厂
 7. RejectedExecutionHandler handler--------------------拒绝策略

对于这个7个参数线程池是如何使用的呢,接着往下看,线程池的执行流程:
1、当向线程池提交任务时,会去创建核心线程
2、当任务太多,核心线程来不及处理时,会将任务先放入任务队列
3、当任务队列满了,会去创建新的线程处理任务,但不会超过最大线程数
4、当线程空闲超过我们设置的时间大小,则回去销毁(核心线程数-最大线程数)之间的线程
5、当队列已满,总线程数已达我们设置的最大线程数时,新的任务进来则会触发我们设置的拒绝策略

总结:也即是说在线程池队列已满,且已创建到最大线程数量时,新的任务提交至线程池,线程池无法处理新的任务,则会对新的任务线程进行丢弃,抛异常,优先处理,丢弃队列中最久等待任务,这些对新的任务线程的处理则称之为线程池的拒绝策略

二、拒绝策略有哪些

1、RejectedExecutionHandler(拒绝执行处理程序)

线程池中的拒绝策略都实现了RejectedExecutionHandler下rejectedExecution方法:

public interface RejectedExecutionHandler {

    /**
     * Method that may be invoked by a {@link ThreadPoolExecutor} when
     * {@link ThreadPoolExecutor#execute execute} cannot accept a
     * task.  This may occur when no more threads or queue slots are
     * available because their bounds would be exceeded, or upon
     * shutdown of the Executor.
     *
     * <p>In the absence of other alternatives, the method may throw
     * an unchecked {@link RejectedExecutionException}, which will be
     * propagated to the caller of {@code execute}.
     *
     * @param r the runnable task requested to be executed
     * @param executor the executor attempting to execute this task
     * @throws RejectedExecutionException if there is no remedy
     */
    void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

丢弃策略(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) {
        }
    }

1、可以在方法rejectedExecution看到,没有任何的代码处理逻辑,也就是对新的任务不做任何处理,翻译过来就是丢弃策略,业务中慎用。

中止策略(AbortPolicy )

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());
        }
    }

1、在代码中可见,在rejectedExecution方法中抛出了RejectedExecutionException异常,会对代码的运行进行中止。

优先处理策略(CallerRunsPolicy )

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();
            }
        }
    }

1、对新的任务进行优先执行,直接调用其run方法

丢弃最老任务(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);
            }
        }
    }

1、拿到队列,调用队列的poll方法对队列中最老的任务进行丢弃,再将新的任务放入队列中

;