写点什么

【线程池饱和策略】线程池饱和策略及自定义方法

  • 2025-08-01
    福建
  • 本文字数:1683 字

    阅读完需:约 6 分钟

常见的线程池饱和策略及使用场景


当线程池的任务队列已满且线程数达到最大值时,新的任务会触发饱和策略(拒绝策略)。Java 提供了四种默认策略:


1、AbortPolicy(默认策略)

行为:直接抛出 RejectedExecutionException 异常。

适用场景

需要严格保证任务不丢失的场景(如支付交易)。

调用方需明确感知任务提交失败,以便回滚或重试。

示例:金融系统中订单处理,失败需立即告警。


2、CallerRunsPolicy

行为:由提交任务的线程(调用者线程)直接执行该任务。

适用场景

需要避免任务丢失,且能接受任务执行速度下降。

利用调用线程执行任务,变相限制新任务提交速率(负反馈)。

示例:Web 服务器处理请求,高峰期用用户线程执行任务,防止雪崩。


3、DiscardPolicy

行为:直接丢弃新任务,无任何通知。

适用场景

允许静默丢弃非关键任务(如日志收集)。

对实时性要求低且可容忍数据丢失的场景。

示例:监控数据上报,丢弃部分数据不影响整体统计。


4、DiscardOldestPolicy

行为:丢弃队列中最旧的任务(队首),然后重试提交新任务。

适用场景

新任务优先级高于旧任务(如实时消息推送)。

可容忍历史任务延迟或丢失。

注意:优先队列中“最旧”不一定是提交时间最早,而是优先级最低。

示例:股票价格更新,最新价格比历史价格更重要。


如何自定义饱和策略?

通过实现 RejectedExecutionHandler 接口并重写 rejectedExecution 方法:

import java.util.concurrent.RejectedExecutionHandler;import java.util.concurrent.ThreadPoolExecutor;
public class CustomRejectionPolicy implements RejectedExecutionHandler { @Override public void rejectedExecution(Runnable task, ThreadPoolExecutor executor) { // 自定义处理逻辑(示例:记录日志 + 重试一次) System.err.println("任务被拒绝: " + task); if (!executor.isShutdown()) { // 重试一次 executor.execute(task); System.out.println("任务重试提交成功"); } }}
复制代码


使用自定义策略

import java.util.concurrent.*;
public class ThreadPoolDemo { public static void main(String[] args) { // 创建线程池并指定自定义策略 ThreadPoolExecutor executor = new ThreadPoolExecutor( 2, // 核心线程数 4, // 最大线程数 60, TimeUnit.SECONDS, new ArrayBlockingQueue<>(2), // 容量为2的队列 new CustomRejectionPolicy() // 自定义饱和策略 );
// 提交任务(模拟饱和) for (int i = 0; i < 10; i++) { executor.execute(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }); } executor.shutdown(); }}
复制代码


自定义策略的常见实践


1、记录日志/告警

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {    log.error("任务拒绝: {}", r, new RejectedException());}
复制代码


2、暂存到数据库/Redis

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {    taskRedisQueue.save(r); // 保存到外部存储,后续恢复}
复制代码


3、有限次重试

private int maxRetries = 3;public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {    if (retryCount.getAndIncrement() < maxRetries) {        e.execute(r); // 重试提交    }}
复制代码


4、降级处理

public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {    runFallbackService((Task) r); // 执行降级逻辑}
复制代码


总结



自定义策略:通过实现 RejectedExecutionHandler 接口,可结合业务需求实现降级、重试、持久化等灵活逻辑。


文章转载自:佛祖让我来巡山

原文链接:https://www.cnblogs.com/sun-10387834/p/18974497

体验地址:http://www.jnpfsoft.com/?from=001YH

用户头像

还未添加个人签名 2023-06-19 加入

还未添加个人简介

评论

发布
暂无评论
【线程池饱和策略】线程池饱和策略及自定义方法_Java_不在线第一只蜗牛_InfoQ写作社区