Java自定义拒绝策略与线程池

本文详细介绍了Java线程池中的四种拒绝策略:AbortPolicy、CallerRunsPolicy、DiscardOldestPolicy及DiscardPolicy,并展示了如何自定义线程创建ThreadFactory。这些策略决定了当线程池无法接受更多任务时的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、拒绝策略

ThreadPoolExcetor 的最后一个参数指定了拒绝策略,JDK提供了四种拒绝策略:
AbortPolicy 策略、CallerRunsPolicy策略、 DiscardOledestPolicy策略、DiscardPolicy策略。

AbortPolicy策略:该策略会直接抛出异常,阻止系统正常工作。

CallerRunsPolicy 策略:只要线程池未关闭,该策略直接在调用者线程中,运行当前的被丢弃的任务。

DiscardOleddestPolicy策略: 该策略将丢弃最老的一个请求,也就是即将被执行的任务,并尝试再次提交当前任务。

DiscardPolicy策略:该策略默默的丢弃无法处理的任务,不予任何处理。

这种策略和上一种,实际上正好是相反的策略,一种是丢弃最新的任务,一个是丢弃最老的任务。

下面看一下源码的具体实现

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


和上面的解释完全一样,就是抛出一个异常。



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




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


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

2、自定义线程创建 ThreadFactory

线程池中创建的线程就是通过ThreadFactory来实现的。

Thread newThread(Runnable r);

下面是一个线程池中自定义创建线程的示例

ExecutorService es = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>(), new ThreadFactory() {

            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setDaemon(true);
                System.out.println("create" + t);
                return null;
            }
        });

自定义创建线程,以及自定义拒绝策略

    ExecutorService es2 = new ThreadPoolExecutor(5, 5, 0L, TimeUnit.MILLISECONDS, new SynchronousQueue<Runnable>(), new ThreadFactory() {

            public Thread newThread(Runnable r) {
                Thread t = new Thread(r);
                t.setDaemon(true);
                System.out.println("create" + t);
                return null;
            }

        }, new RejectedExecutionHandler() {

            public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
                 System.out.println(r.toString()+" is discard");

            }

        });

Java 自定义线程池和 Tomcat 线程池在功能上都用于管理线程资源以提高并发性能,但在实现方式、配置策略以及应用场景上有显著区别。 ### 工作机制线程调度方式 Java 自定义线程池通常基于 `ThreadPoolExecutor` 实现,其工作流程遵循标准的线程池模式:首先使用核心线程(corePoolSize)处理任务,当核心线程满载时,将任务放入队列中等待;只有当队列已满且未达到最大线程数(maximumPoolSize)时,才会创建新的非核心线程来处理任务。这种方式更注重资源的合理利用和任务调度的灵活性[^3]。 Tomcat 线程池则采用了不同的策略,其设计目标是快速响应 HTTP 请求。Tomcat 的线程池会优先创建新线程来处理请求,直到达到 `maxThreads` 所设定的最大线程数。只有在所有线程都被占用的情况下,才会将请求放入队列中排队等待。这种机制更适合 Web 服务器对突发流量的快速响应需求[^1]。 ### 配置参数对比 Java 自定义线程池的核心参数包括: - `corePoolSize`:核心线程数。 - `maximumPoolSize`:最大线程数。 - `keepAliveTime`:空闲线程存活时间。 - `workQueue`:任务队列。 - `threadFactory`:线程工厂。 - `handler`:拒绝策略。 而 Tomcat 线程池主要涉及以下关键配置: - `maxThreads`:等同于最大线程数,表示 Tomcat 能够创建的最大工作线程数。 - `minSpareThreads`:最小空闲线程数,即使没有请求,也会保持一定数量的空闲线程以应对突发请求。 - `acceptCount`:最大排队请求数,当所有线程都在忙时,新的请求会进入该队列等待执行[^1]。 ### 线程工厂可配置性 Java 自定义线程池可以通过实现 `ThreadFactory` 接口来自定义线程的创建逻辑,例如设置线程名称、优先级、是否为守护线程等。通过自定义线程工厂类,可以实现线程命名的统一管理,并支持参数的可配置化,便于生产环境中不同业务模块的使用。此外,在系统配置值不生效时,可以提供默认值以增强系统的健壮性和适应性[^2]。 Tomcat 线程池虽然也支持一定程度的定制化,但其线程创建过程由内部机制控制,开发者通常不需要直接干预线程的创建逻辑。不过,Tomcat 提供了丰富的配置选项来满足不同场景下的性能调优需求。 ### 应用场景差异 Java 自定义线程池适用于通用的并发任务处理,如定时任务、异步处理、批量数据计算等场景。它提供了较高的灵活性,适合需要精细控制线程生命周期和任务调度的应用。 Tomcat 线程池专为 Web 容器设计,主要用于处理 HTTP 请求。其优化方向是快速响应客户端请求,尤其在高并发场景下表现优异。因此,它更适合部署在 Web 服务器或应用服务器中,用于支撑 Web 应用的并发处理能力。 --- ```java // 示例:自定义线程工厂类 public class CustomThreadFactory implements ThreadFactory { private final AtomicInteger atomicInteger = new AtomicInteger(1); private final String namePrefix; private final boolean isDaemon; public CustomThreadFactory(String prefix, boolean daemon) { if (StringUtils.isNoneBlank(prefix)) { this.namePrefix = prefix; } else { this.namePrefix = "thread_pool"; } isDaemon = daemon; } @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r, namePrefix + "-" + atomicInteger.getAndIncrement()); thread.setDaemon(isDaemon); if (thread.getPriority() != Thread.NORM_PRIORITY) { thread.setPriority(Thread.NORM_PRIORITY); } return thread; } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值