线程池的拒绝策略:优化处理能力的关键

一:前言

        在多线程编程中,线程池是一种常用的工具,可以有效管理和调度大量的线程任务。然而,在高负载情况下,线程池可能无法接受新的任务,这就需要定义一种拒绝策略来处理这种情况。本文将介绍线程池的拒绝策略,以及如何选择合适的策略来优化处理能力。

二:什么是线程池的拒绝策略?

        线程池的拒绝策略是在线程池无法接受新任务时采取的一种处理方式。当线程池中的线程已经达到最大容量并且队列已满时,新的任务将会被拒绝。拒绝策略定义了线程池如何处理这些被拒绝的任务,以避免任务丢失或造成系统崩溃。

三: 拒绝策略的四种类型

        Java线程池提供了几种内置的拒绝策略,包括以下几种:

        (1) AbortPolicy(默认策略)

        该策略直接抛出RejectedExecutionException异常,阻止线程池接受新任务。这是最简单和最直接的拒绝方式,但可能会丢失部分任务。

        (2) CallerRunsPolicy

        该策略将任务回退给调用者执行,而不是在新的线程中执行。当线程池无法接受新任务时,任务会由提交任务的线程执行。这种策略可能会降低系统的吞吐量,但能够保证任务的执行,避免任务丢失。

        (3) DiscardPolicy

        该策略直接丢弃无法处理的任务,没有任何异常抛出。这种策略可能会导致部分任务被忽略掉,无法正常执行。

        (4) DiscardOldestPolicy

        该策略先丢弃队列中等待时间最长的任务,然后尝试将新任务加入队列。这种策略可以保证新任务得到执行,但可能会丢失部分等待时间较长的任务。

四:四种线程池拒绝策略的分析

        当线程池的任务缓存队列已满并且线程池中的线程数目达到maximumPoolSize时,如果还有任务到来就会采取任务拒绝策略,通常有以下四种策略:

ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2,5,3,TimeUnit.SECONDS,
         // 候客区
         new LinkedBlockingDeque<>(3), 
         // 默认线程工厂
         Executors.defaultThreadFactory(), 
         // 默认的拒绝策略,银行满了还有人进来,不处理,抛出异常
         new ThreadPoolExecutor.AbortPolicy() 
              // 拒绝策略,哪来的去哪里
//            new ThreadPoolExecutor.CallerRunsPolicy() 
              // 拒绝策略, 队列满了不会抛出异常
//            new ThreadPoolExecutor.DiscardPolicy()  
              // 拒绝策略,队列满了,尝试去和最早的竞争,不会抛出异常
//            new ThreadPoolExecutor.DiscardOldestPolicy()  
 );

(1) AbortPolicy(默认策略)

        ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。 

A handler for rejected tasks that throws a {@code RejectedExecutionException}.

        这是线程池默认的拒绝策略,在任务不能再提交的时候,抛出异常,及时反馈程序运行状态。如果是比较关键的业务,推荐使用此拒绝策略,这样子在系统不能承载更大的并发量的时候,能够及时的通过异常发现。

 (2) CallerRunsPolicy

        ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务

A handler for rejected tasks that runs the rejected task directly in the calling thread of the {@code execute} method, unless the executor has been shut down, in which case the task is discarded.
 

        如果任务被拒绝了,则由调用线程(提交任务的线程)直接执行此任务 

(3) DiscardPolicy

        ThreadPoolExecutor.DiscardPolicy:丢弃任务,但是不抛出异常。如果线程队列已满,则后续提交的任务都会被丢弃,且是静默丢弃。

A handler for rejected tasks that silently discards therejected task.

        使用此策略,可能会使我们无法发现系统的异常状态。建议是一些无关紧要的业务采用此策略。例如,本人的博客网站统计阅读量就是采用的这种拒绝策略。

(4) DiscardOldestPolicy

        ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新提交被拒绝的任务。

A handler for rejected tasks that discards the oldest unhandled request and then retries {@code execute}, unless the executor is shut down, in which case the task is discarded.

        此拒绝策略,是一种喜新厌旧的拒绝策略。是否要采用此种拒绝策略,还得根据实际业务是否允许丢弃老任务来认真衡量。

五:如何选择合适的拒绝策略?

选择适合的拒绝策略取决于具体的业务需求和系统环境:

  • 如果系统对任务丢失比较敏感,可以选择CallerRunsPolicy,保证任务得到执行,但要注意这可能会影响系统的吞吐量。
  • 如果系统对任务丢失并不敏感,可以选择DiscardPolicy或DiscardOldestPolicy。前者会直接丢弃任务,而后者会丢弃等待时间最长的任务。
  • 如果系统对任务的完整性要求较高,可以选择AbortPolicy,并在任务被拒绝时及时处理RejectedExecutionException异常。

此外,也可以根据具体情况实现自定义的拒绝策略。通过实现RejectedExecutionHandler接口,可以定义自己的拒绝策略逻辑,例如将拒绝的任务记录下来,或者将任务重新放入队列等。

六:总结

        线程池的拒绝策略是优化处理能力的关键。选择合适的拒绝策略可以避免任务丢失,并根据业务需求和系统环境来权衡吞吐量和任务完整性。了解不同拒绝策略的特点和使用场景,可以帮助我们更好地设计和管理线程池

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在 Spring Boot 中,你可以使用 ThreadPoolTaskExecutor 类来配置线程池,并且可以设置拒绝策略处理任务队列满时的情况。 以下是一些常见的线程池拒绝策略: 1. AbortPolicy(默认):当任务队列已满时,新任务将被直接丢弃,并抛出 RejectedExecutionException 异常。 2. CallerRunsPolicy:当任务队列已满时,新任务会由调用线程(提交任务的线程)直接执行。这可能会降低整体的吞吐量,但可以避免任务丢失。 3. DiscardPolicy:当任务队列已满时,新任务将被直接丢弃,不会抛出任何异常。这种策略可能会导致未执行的任务较多。 4. DiscardOldestPolicy:当任务队列已满时,将尝试将最早的任务从队列中移除,然后再尝试添加新任务。如果移除成功,将会尝试再次提交当前任务。 你可以使用 ThreadPoolTaskExecutor 类的 setRejectedExecutionHandler() 方法来设置线程池拒绝策略,例如: ```java import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(10); executor.setMaxPoolSize(100); executor.setQueueCapacity(1000); executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy()); executor.initialize(); ``` 在上面的示例中,我们使用了 AbortPolicy 拒绝策略。你可以根据实际需求选择适合的拒绝策略处理任务队列满时的情况。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值