【Java并发编程】线程池的四种拒绝策略(饱和策略)

news/2024/10/21 1:58:44/

引入

线程池的拒绝策略是当线程池出现以下情况时,由于线程池达到其容量上限而无法接受新任务时的处理机制:

  1. 线程池已满:当线程池中的所有线程都在执行任务时,新提交的任务无法立即执行。这种情况发生在当前线程池的核心线程和最大线程数都已被占用时。
  2. 任务队列已满:当线程池的任务队列(如 LinkedBlockingQueue)已满,新的任务无法被放入队列中等待执行。

在 Java 的并发包(java.util.concurrent)中,ThreadPoolExecutor 提供了四种内置的线程池拒绝策略 (RejectedExecutionHandler)来应对线程池达到其容量限制时,采取适当的策略来处理这些额外的任务。
四种内置拒绝策略适用场景如下,在挑选拒绝策略时需要根据具体的需求选择合适的策略:

策略说明适用场景
AbortPolicy抛出 RejectedExecutionException任务执行必须完成,不能丢失任务的场景,如实时数据处理系统。
CallerRunsPolicy调用 execute() 方法在调用线程中运行任务任务提交者自己执行任务,适用于负载较低时避免任务丢失的场景。
DiscardPolicy忽略被拒绝的任务,不做任何处理任务丢失可以接受,优先处理重要任务的场景,如缓存更新。
DiscardOldestPolicy丢弃队列中最旧的任务并尝试提交新任务需要保留最新任务,但可以丢弃较旧任务的场景,如短时间内的数据采集。

线程池的四种拒绝策略

1. AbortPolicy

默认的拒绝策略。如果线程池和队列都满了,并且无法接受新任务时,AbortPolicy 策略会直接终止任务提交并抛出 RejectedExecutionException 异常。

java">new ThreadPoolExecutor.AbortPolicy();

使用这种策略时,调用者需要处理异常,确保程序不会因为任务被拒绝而崩溃。适用于任务提交者可以控制和处理异常的场景。

示例

java">ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 60, TimeUnit.SECONDS,new LinkedBlockingQueue<>(2),new ThreadPoolExecutor.AbortPolicy()
);

2. CallerRunsPolicy

当任务被拒绝时,CallerRunsPolicy 策略会由任务提交者线程来执行被拒绝的任务,而不是由线程池中的线程来执行。

java">new ThreadPoolExecutor.CallerRunsPolicy();

这种策略可以减缓任务提交的速度,避免过度负荷线程池。适用于希望通过降低提交速率来缓解线程池压力的场景。

示例

java">ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 60, TimeUnit.SECONDS,new LinkedBlockingQueue<>(2),new ThreadPoolExecutor.CallerRunsPolicy()
);

3. DiscardPolicy

当任务被拒绝时,DiscardPolicy 策略会将被拒绝的任务丢弃,没有任何通知或异常抛出。

java">new ThreadPoolExecutor.DiscardPolicy();

这种策略采取丢弃任务的方式可能会导致任务丢失,但有助于防止线程池崩溃或性能严重下降,适用于对丢弃任务没有特别要求的场景。

示例

java">ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 60, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>(2),new ThreadPoolExecutor.DiscardPolicy()
);

4. DiscardOldestPolicy

如果线程池和队列都满了,DiscardOldestPolicy 会丢弃任务队列中最旧的任务,然后尝试提交新的任务。

java">new ThreadPoolExecutor.DiscardOldestPolicy();

这种策略可以确保新的任务被处理,但会丢弃最早的任务,可能会丢失一些重要任务。适用于希望保留最新任务的场景。

示例

java">ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 2, 0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>(2),new ThreadPoolExecutor.DiscardOldestPolicy()
);

自定义拒绝策略

除了内置的策略,我们可以通过实现自定义的 RejectedExecutionHandler 接口来创建自定义拒绝策略。

java">public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {// 自定义处理逻辑,比如记录日志、重新排队等System.out.println("任务被拒绝: " + r.toString());}
}

例如,我们可以实现一个自定义的拒绝策略,当任务被拒绝时会尝试重试提交任务:

java">public class RequeueRejectedExecutionHandler implements RejectedExecutionHandler {@Overridepublic void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {// 将被拒绝的任务重新排队System.out.println("任务被拒绝,正在重新排队: " + r.toString());// 尝试将任务重新提交到线程池if (!executor.isShutdown()) {try {Thread.sleep(1000);// 直接调用execute方法进行重新排队executor.execute(r);} catch (Exception e) {System.err.println("重新提交任务失败: " + e.getMessage());}}}
}

但是在实际应用中,我们应避免任务被无限重试,应该确保在达到最大重试次数后,任务能够被丢弃或者按照某种策略处理。


http://www.ppmy.cn/news/1540658.html

相关文章

卷积神经网络(CNN)-Padding介绍

在卷积过程中,输出特征图的大小由输入特征图的大小、内核的大小和步幅决定。如果我们简单地在输入特征图上应用内核,那么输出特征图将小于输入。这可能会导致输入特征图边界处的信息丢失。为了保留边框信息,我们使用padding。 什么是填充 Padding是一种技术,用于在对特征…

C++ 类的基础用法与详细说明:简单易懂的入门指南

什么是类&#xff1f; C类_百度百科 类是C中一种用于封装数据和功能的基本结构。你可以将类视为一种自定义的数据类型&#xff0c;它可以包含数据&#xff08;成员变量&#xff09;和操作这些数据的函数&#xff08;成员函数&#xff09;。 创建一个简单的类 让我们通过一个…

【Golang】踩坑记录:make()创建引用类型,初始值是不是nil!!

文章目录 起因二、得记住的知识点1. make()切片&#xff0c;初始化了吗&#xff1f;2. make()切片不同长度容量&#xff0c;append时的差别3. 切片是指向数组的指针吗&#xff1f;4. 切片扩容时&#xff0c;重新分配内存&#xff0c;原切片的数据怎么办&#xff1f; 三、咳咳&a…

CLion和Qt 联合开发环境配置教程(Windows和Linux版)

需要安装的工具CLion 和Qt CLion下载链接 :https://www.jetbrains.com.cn/clion/ 这个软件属于直接默认安装就行&#xff0c;很简单&#xff0c;不多做介绍了 Qt:https://mirrors.tuna.tsinghua.edu.cn/qt/official_releases/online_installers/ window 直接点exe Linux 先c…

http大数据post与put请求

大数据请求情况下出现post请求提交出错而put请求提交不出错 一、http方法特性差异 1、请求语义和用途不同 post通常用于 创建新资源Put一般用于更新现有资源服务器对于不同的HTTP方法可能有不同的处理逻辑和优化策略。在某些情况下&#xff0c;服务器可能对put请求的处理更加…

大厂面试提问:Flash Attention 是怎么做到又快又省显存的?

最近已有不少大厂都在秋招宣讲了&#xff0c;也有一些在 Offer 发放阶段。 节前&#xff0c;我们邀请了一些互联网大厂朋友、今年参加社招和校招面试的同学。 针对新手如何入门算法岗、该如何准备面试攻略、面试常考点、大模型技术趋势、算法项目落地经验分享等热门话题进行了…

Scala中的reduce

作用&#xff1a;reduce是一种集合操作&#xff0c;用于对集合中的元素进行聚合操作&#xff0c;返回一个单一的结果。它通过指定的二元操作&#xff08;即取两个元素进行操作&#xff09;对集合中所有的元素进行递归处理&#xff0c;并最终将其合并为一个值。 语法&#xff1…

在合规的地方怎么用EACO地球链兑换交换价值?

地球链EACO&#xff08;EarthChain&#xff0c;简称$E&#xff09;是一种虚拟数字资产。 目前在中国大陆&#xff0c;虚拟资产相关业务活动属于金融活动&#xff0c;包括虚拟资产的交易、兑换等操作&#xff0c;因此应该谨慎去寻求如何用它来交换价值。 虚拟资产交易炒作活动&…