Java实现自定义线程池拒绝策略的完整代码

 更新时间:2026年02月03日 09:01:24   作者:康小庄  
自定义拒绝策略的核心是实现java.util.concurrent.RejectedExecutionHandler接口,这篇文章主要介绍了如何使用Java实现自定义线程池拒绝策略,感兴趣的小伙伴可以了解下

自定义拒绝策略的核心是实现java.util.concurrent.RejectedExecutionHandler接口,重写唯一的rejectedExecution(Runnable r, ThreadPoolExecutor executor)方法:

  • 参数r:被线程池拒绝的任务实例;
  • 参数executor:当前线程池实例,可通过它获取实时运行状态(活跃线程数、队列任务数、完成任务数等),用于问题排查。
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 自定义拒绝策略Demo:详细日志+线程池状态监控
 */
public class CustomRejectPolicyDemo {

    // 1. 实现RejectedExecutionHandler,自定义拒绝策略
    static class MyCustomRejectPolicy implements RejectedExecutionHandler {
        @Override
        public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
            // 核心:打印详细拒绝日志 + 线程池实时状态(生产级排查必备)
            String rejectLog = String.format(
                    "===== 任务被拒绝 =====\n" +
                    "拒绝时间:%s\n" +
                    "被拒任务:%s\n" +
                    "线程池状态:运行中=%s | 核心线程数=%d | 最大线程数=%d\n" +
                    "当前状态:活跃线程数=%d | 队列任务数=%d | 已完成任务数=%d | 总任务数=%d",
                    System.currentTimeMillis(),
                    r.toString(),
                    executor.isRunning(), // 线程池是否处于RUNNING状态
                    executor.getCorePoolSize(),
                    executor.getMaximumPoolSize(),
                    executor.getActiveCount(), // 实时活跃线程数
                    executor.getQueue().size(), // 队列中等待的任务数
                    executor.getCompletedTaskCount(), // 已完成的任务总数
                    executor.getTaskCount() // 提交的总任务数(完成+执行中+队列中)
            );
            // 实际生产中可替换为SLF4J/Logback日志框架
            System.err.println(rejectLog);
            // 可选:根据业务需求扩展(如任务持久化到MQ/Redis、触发限流告警、主线程兜底执行等)
        }
    }

    // 2. 自定义线程工厂(可选,用于设置线程名,便于排查任务执行线程)
    static class MyThreadFactory implements ThreadFactory {
        private final AtomicInteger threadId = new AtomicInteger(1);
        private final String threadPrefix = "biz-worker-thread-";

        @Override
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r, threadPrefix + threadId.getAndIncrement());
            thread.setDaemon(false); // 非守护线程,保证任务执行完成
            thread.setPriority(Thread.NORM_PRIORITY); // 正常优先级
            return thread;
        }
    }

    // 主程序:测试自定义拒绝策略
    public static void main(String[] args) throws InterruptedException {
        // 线程池核心参数:故意设置小参数,方便触发拒绝策略
        int corePoolSize = 2;    // 核心线程数
        int maximumPoolSize = 4; // 最大线程数
        long keepAliveTime = 1;  // 非核心线程空闲超时时间
        int queueCapacity = 2;   // 任务队列容量(有限队列,必选,否则无法触发拒绝策略)

        // 3. 创建线程池,指定【自定义拒绝策略】
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                corePoolSize,
                maximumPoolSize,
                keepAliveTime,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(queueCapacity), // 有限容量队列,触发拒绝策略的关键
                new MyThreadFactory(), // 自定义线程工厂(可选)
                new MyCustomRejectPolicy() // 核心:指定自定义拒绝策略
        );

        try {
            // 提交7个任务,触发拒绝策略(2核心+2队列+2非核心=6,第7个任务被拒绝)
            for (int i = 1; i <= 7; i++) {
                int taskId = i;
                executor.submit(() -> {
                    try {
                        // 模拟任务执行耗时1秒
                        TimeUnit.SECONDS.sleep(1);
                        System.out.printf("任务%d执行成功,执行线程:%s%n", taskId, Thread.currentThread().getName());
                    } catch (InterruptedException e) {
                        Thread.currentThread().interrupt();
                        System.out.printf("任务%d被中断%n", taskId);
                    }
                });
                System.out.printf("任务%d已提交%n", taskId);
            }
        } finally {
            // 4. 优雅关闭线程池(必须,避免资源泄漏)
            executor.shutdown();
            // 等待线程池终止,超时则强制关闭
            if (!executor.awaitTermination(5, TimeUnit.SECONDS)) {
                executor.shutdownNow();
            }
        }
    }
}

本次线程池参数设置为核心2+最大4+队列2总处理能力 = 6(2 核心线程执行 + 2 队列等待 + 2 非核心线程执行),提交第 7 个任务时,满足任务队列已满 + 线程数达到 maximumPoolSize,触发自定义拒绝策略。

任务1已提交
任务2已提交
任务3已提交
任务4已提交
任务5已提交
任务6已提交
任务7已提交
===== 任务被拒绝 =====
拒绝时间:1738456200000
被拒任务:java.util.concurrent.FutureTask@1b6d3586
线程池状态:运行中=true | 核心线程数=2 | 最大线程数=4
当前状态:活跃线程数=4 | 队列任务数=2 | 已完成任务数=0 | 总任务数=7
任务1执行成功,执行线程:biz-worker-thread-1
任务2执行成功,执行线程:biz-worker-thread-2
任务3执行成功,执行线程:biz-worker-thread-3
任务4执行成功,执行线程:biz-worker-thread-4
任务5执行成功,执行线程:biz-worker-thread-1
任务6执行成功,执行线程:biz-worker-thread-2

  • 自定义拒绝策略必须实现RejectedExecutionHandler接口,重写rejectedExecution方法;
  • 触发拒绝策略的唯一条件:任务队列已满 + 线程池当前线程数达到maximumPoolSize
  • 通过ThreadPoolExecutor实例可获取全量运行状态,是生产排查任务拒绝问题的关键;
  • 线程池必须使用有限容量队列,否则任务会无限入队,拒绝策略永远不会生效;
  • 业务结束后必须优雅关闭线程池shutdown()+awaitTermination()),避免资源泄漏。

到此这篇关于Java实现自定义线程池拒绝策略的完整代码的文章就介绍到这了,更多相关Java拒绝策略内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaOOP封装实例解读

    JavaOOP封装实例解读

    封装通过private限制属性访问,提供get/set方法控制数据读写,确保值合法,示例中Student类属性私有,Test类需调用set方法赋值并验证,get方法获取值,实现数据隐藏与安全操作
    2025-09-09
  • IDEA中文乱码的几种常见解决方案

    IDEA中文乱码的几种常见解决方案

    IntelliJ IDEA 如果不进行相关设置,可能会导致控制台中文乱码、配置文件中文乱码等问题,非常影响编码过程中进行问题追踪,所以本文给大家介绍了IDEA中文乱码的几种常见解决方案,需要的朋友可以参考下
    2025-04-04
  • WebClient抛UnsupportedMediaTypeException异常解决

    WebClient抛UnsupportedMediaTypeException异常解决

    这篇文章主要为大家介绍了WebClient抛UnsupportedMediaTypeException异常的解决方案,文中给大家介绍了六中方案,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2022-02-02
  • 分布式医疗挂号系统EasyExcel导入导出数据字典的使用

    分布式医疗挂号系统EasyExcel导入导出数据字典的使用

    这篇文章主要为大家介绍了分布式医疗挂号系统EasyExcel导入导出数据字典的使用,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • Spring IoC容器与Bean管理项目实践指南

    Spring IoC容器与Bean管理项目实践指南

    IoC容器的主要作用是解决组件之间的耦合问题,通过将组件之间的依赖关系交给IoC容器来管理,可以在不改变组件的代码的情况下实现组件之间的解耦,这篇文章主要介绍了Spring IoC容器与Bean管理项目的相关资料,需要的朋友可以参考下
    2025-08-08
  • SpringBoot之自定义Filter获取请求参数与响应结果案例详解

    SpringBoot之自定义Filter获取请求参数与响应结果案例详解

    这篇文章主要介绍了SpringBoot之自定义Filter获取请求参数与响应结果案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-09-09
  • Java中的迭代器和foreach原理

    Java中的迭代器和foreach原理

    这篇文章主要介绍了Java中的迭代器和foreach原理,帮助大家更好的理解和学习Java,感兴趣的朋友可以了解下
    2020-09-09
  • Java注解处理器简单实例

    Java注解处理器简单实例

    这篇文章主要介绍了Java注解处理器简单实例,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • Leetcode常见链表问题及代码示例

    Leetcode常见链表问题及代码示例

    这篇文章主要介绍了Leetcode常见链表问题及代码示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11
  • SpringBoot请求参数相关注解说明小结

    SpringBoot请求参数相关注解说明小结

    这篇文章主要介绍了SpringBoot请求参数相关注解说明,主要包括@PathVariable,@RequestHeader、@CookieValue、@RequestBody和@RequestParam,本文结合实例代码给大家讲解的非常详细,需要的朋友可以参考下
    2022-05-05

最新评论