当线程池拒绝任务时,应通过监控getRejectedExecutionCount()实时感知并触发自动入队备份机制。需每秒采样1–2次、用滑动窗口判断持续过载,拒绝任务异步移交至MQ或本地存储,备份后由独立消费者恢复执行,并配套监控与限流闭环。

当线程池拒绝任务时,说明系统已处于过载临界点。此时单纯抛异常或丢任务不可取,而通过监控 getRejectedExecutionCount() 实时感知拒绝行为,并联动触发“自动入队备份”机制,是保障任务不丢失的关键实战手段。
监控拒绝次数的可靠方式
ThreadPoolExecutor 提供了原子计数的 getRejectedExecutionCount() 方法,该值在每次触发拒绝策略时自增,线程安全、无需额外同步。
- 避免轮询频率过高:建议每秒采样 1–2 次,结合滑动窗口(如最近 10 秒累计值)判断是否持续过载
- 注意初始化延迟:该计数器从 0 开始,首次拒绝后才非零,需确保监控逻辑在 executor 启动后生效
- 区分瞬时尖峰与持续过载:单次突增可能为毛刺,推荐使用「连续 N 次采样均 > 阈值」作为触发条件(如 3 秒内每秒拒绝 ≥5 次)
拒绝发生时自动转入备份队列的实现要点
不是在拒绝策略里直接写库或发 MQ(会阻塞主线程),而是将拒绝任务异步移交至高可用备份通道:
- 使用独立的、带失败重试的内存缓冲队列(如 Disruptor 或 BlockingQueue + 定时刷出线程)暂存被拒任务
- 备份目标优先选消息队列(如 RocketMQ/Kafka):序列化 Runnable 为 JSON(含类名、参数、时间戳),设置合理超时与死信策略
- 若 MQ 不可用,降级写入本地文件或数据库表(如
backup_task表,字段含 task_data、status、retry_count、create_time) - 所有备份操作必须设置超时(如 500ms)和熔断开关,防止备份链路拖垮主流程
备份任务的后续消费与执行保障
备份不是终点,而是异步恢复的起点:
- 单独部署消费者服务,从 MQ 或 DB 拉取待执行任务,按原始语义反序列化并提交至线程池(注意幂等性设计)
- 对备份任务增加 TTL(如 2 小时),超时未执行则标记为失效并告警
- 记录备份成功率、重试次数、最终执行耗时等指标,接入统一监控大盘,形成闭环
- 可配合限流组件(如 Sentinel)动态调整上游流量,当拒绝率回落至阈值以下,逐步放开限流
一个轻量可行的落地结构示意
不引入复杂框架也能快速上线:
- 定义全局备份调度器:
BackupTaskDispatcher,持有 RocketMQProducer 和 fallback JdbcTemplate - 自定义拒绝策略中仅做快速入内存队列:
backupQueue.offer(task)(无阻塞、不抛异常) - 后台线程定时(如每 200ms)批量取出内存队列任务,异步发送至 MQ;失败则落库,失败再失败则记日志+告警
- 配套提供管理接口:查询当前积压备份数、手动触发重试、清空异常堆积

















