# 39. 线程池拒绝策略分析

# 标准答案

✅ 线程池拒绝策略的选择和设计:

  1. JDK内置拒绝策略

    • AbortPolicy:直接抛出异常(默认策略)
    • CallerRunsPolicy:由调用线程执行任务
    • DiscardPolicy:直接丢弃任务
    • DiscardOldestPolicy:丢弃队列最旧任务
  2. 自定义拒绝策略场景

    • 任务降级处理
    • 任务延迟处理
    • 任务优先级处理
    • 任务日志记录
    • 任务监控告警
  3. 最佳实践建议

    • 核心系统使用CallerRunsPolicy实现优雅降级
    • 非核心系统可以使用DiscardPolicy
    • 监控系统必须使用自定义策略记录信息

# 答案解析

# 1️⃣ 内置拒绝策略详解

// AbortPolicy:抛出异常
new ThreadPoolExecutor.AbortPolicy();

// CallerRunsPolicy:调用者执行
new ThreadPoolExecutor.CallerRunsPolicy();

// DiscardPolicy:直接丢弃
new ThreadPoolExecutor.DiscardPolicy();

// DiscardOldestPolicy:丢弃最旧任务
new ThreadPoolExecutor.DiscardOldestPolicy();
1
2
3
4
5
6
7
8
9
10
11

# 2️⃣ 自定义拒绝策略实现

public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        // 1. 记录日志
        log.warn("Task rejected: {}", r);
        
        // 2. 发送监控告警
        AlertUtil.sendAlert("线程池任务拒绝");
        
        // 3. 任务降级处理
        if (r instanceof PriorityTask) {
            handlePriorityTask((PriorityTask) r);
        } else {
            // 普通任务直接丢弃
            log.info("Discard task: {}", r);
        }
    }
    
    private void handlePriorityTask(PriorityTask task) {
        // 优先级任务降级处理
        if (task.getPriority() > 5) {
            // 高优先级任务,尝试延迟处理
            delayQueue.offer(task);
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 常见误区

  • 误区1:认为拒绝策略不重要
  • 误区2:一直使用默认的AbortPolicy

# 典型场景与解决方案

# ✅ 订单处理系统的拒绝策略

public class OrderRejectedHandler implements RejectedExecutionHandler {
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        if (r instanceof OrderTask) {
            OrderTask task = (OrderTask) r;
            // 1. 记录监控指标
            MetricsUtil.recordRejection("order_task");
            
            // 2. 存入延迟队列
            DelayQueue<OrderTask> delayQueue = DelayQueueHolder.getQueue();
            delayQueue.offer(task);
            
            // 3. 发送告警
            if (task.getOrderAmount() > 10000) {
                AlertUtil.sendHighPriorityAlert("高金额订单处理延迟");
            }
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# 企业实战经验

# Situation(业务背景)

支付系统在双11期间遇到流量峰值,线程池出现任务拒绝。

# Task(核心任务)

设计合理的拒绝策略,确保支付业务的稳定性。

# Action(解决方案)

  1. 实现自定义拒绝策略
  2. 对接实时监控系统
  3. 实现任务优先级处理
  4. 设置任务重试机制

# Result(结果)

  • 系统可用性提升到99.99%
  • 重要交易零丢失
  • 监控覆盖率100%

# 深入追问

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

  • 考虑业务重要性
  • 评估系统容量
  • 分析任务特性

🔹 如何处理被拒绝的任务?

  • 实现降级逻辑
  • 使用延迟队列
  • 记录监控数据

# 相关面试题

  1. 线程池的拒绝策略有哪些?
  2. 如何实现自定义拒绝策略?
  3. 不同场景下如何选择拒绝策略?