java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java拒绝策略

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

作者:康小庄

自定义拒绝策略的核心是实现java.util.concurrent.RejectedExecutionHandler接口,这篇文章主要介绍了如何使用Java实现自定义线程池拒绝策略,感兴趣的小伙伴可以了解下

自定义拒绝策略的核心是实现java.util.concurrent.RejectedExecutionHandler接口,重写唯一的rejectedExecution(Runnable r, ThreadPoolExecutor 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

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

您可能感兴趣的文章:
阅读全文