Java线程池ThreadPoolExecutor常见拒绝策略RejectedExecutionHandler详解

编程教程 > Java (36) 2025-01-22 09:16:57

ThreadPoolExecutor 实现的拒绝策略有以下几种

  • AbortPolicy
  • DiscardPolicy
  • DiscardOldestPolicy
  • CallerRunsPolicy

 

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

 

ThreadPoolExecutor.DiscardPolicy

这个策略和AbortPolicy的静默版本,如果线程池队列满了,会直接丢掉这个任务并且不会有任何异常。源码如下:

    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) {
        }
    }

内部啥也没做直接丢掉任务。

 

ThreadPoolExecutor.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);
            }
        }
    }

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

 

如果以上还不能满足需求可以选择实现RejectedExecutionHandler接口自定义策略,入参就是任务和当前线程池对象。接口源码参考:

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

 

 


评论
User Image
提示:请评论与当前内容相关的回复,广告、推广或无关内容将被删除。

相关文章
ThreadPoolExecutor 实现的拒绝策略有以下几种AbortPolicyDiscardPolicyDiscardOldestPolicyCaller
线程池创建 /** * 队列用线程 * @return */ @Bean(name = "queuePool") public Thread...
java多线程编程_java多线程安全_java多线程实现安全锁CAS机制,CAS在java多线程中相当于数据库的乐观锁,synchronized相当于数据库的乐观锁。
Java基础多线程之主线程等待子线程结束,Java基础编程之多线程入门学习篇。主要讲解几种方法来实现Java多线程中主线程等待子线程结束的最快方式。
线程安全是像Java这样的语言/平台中的类的重要质量,我们经常在线程之间共享对象。由于缺乏线程安全性而导致的问题非常难以调试,因为它们零星且几乎不可能有意再现。你如何测试你的对象以确保它们是线程...
摘要上节解决了单一线程的 trace id 传递,如果子线程和线程池怎么办呢,还有 rpc 远程调用,怎么玩呢?我们在做项目中肯定有很多时候希望通过异步的方式来
概述Timer/ScheduledThreadPoolExecutor都是是JDK提供的api Timer Demoimport lombok.extern.s
问题描述最近写JavaFX程序遇到了下面的错误:Exception in thread "pool-2-thread-1" java.lang.IllegalStateException: No...
Spring作为一个IOC/DI容器,帮助我们管理了许许多多的“bean”。但其实,Spring并没有保证这些对象的线程安全,需要由开发者自己编写解决线程安全问题的代码。
Java多线程生命周期
1. 线程的安全性问题:线程安全和非线程安全: 一个类在单线程环境下能够正常运行,并且在多线程环境下,使用方不做特别处理也能运行正常,我们就称其实线程安全的
spring boot 2.0 入门之单元测试多线程。spring boot 2.0 项目含多线程异步处理业务单元测试执行主线程结束不等待子线程结束。
策略模式简介策略设计模式是一种行为模式,其中我们有多种算法/策略来实现任务,以及使用哪种算法/策略供客户选择
参考文章 ThreadLocal在线程池中被串用_threadlocal串数据-CSDN博客流程示意参考文章是过滤器Filter,我这里的情况差不多,拦截器,也