异步重试需动态决策重试时机与策略,基于ScheduledExecutorService实现非阻塞延迟执行、状态管理与异常分类处理,支持指数退避、原子计数、资源清理及轻量可控的SDK级集成。

异步重试不是简单地“失败后隔几秒再调一次”,而是要在异常发生时,动态决定是否重试、重试几次、间隔多久、甚至根据异常类型调整策略。用 ScheduledExecutorService 实现,核心在于:不阻塞主线程、延迟执行重试任务、支持取消与状态管理。
捕获异常并触发延迟重试
关键不是在 try-catch 里直接 sleep + retry(那会阻塞线程),而是捕获异常后,提交一个带延迟的 Runnable 到调度器:
- 每次重试前检查是否已取消或达到最大重试次数
- 将原始参数、当前重试次数、异常信息封装进任务对象,避免闭包变量被覆盖
- 示例逻辑:第一次失败后 100ms 重试,第二次 300ms,第三次 1s(指数退避)
用原子变量控制重试生命周期
避免重复提交或无效重试,需显式管理任务状态:
- 用
AtomicInteger attemptCount记录已执行次数,线程安全递增 - 用
AtomicBoolean isCompleted标记是否已成功或彻底放弃 - 在重试任务开头先判断
isCompleted.get(),为 true 则直接 return
支持按异常类型差异化处理
不是所有异常都值得重试——网络超时可重试,参数校验失败则应立即终止:
- 在 catch 块中用
instanceof或Throwable.getClass().getSimpleName()匹配异常类型 - 对
IOException、TimeoutException允许重试;对IllegalArgumentException、NullPointerException直接标记失败 - 可将重试规则抽象为
RetryPolicy接口,实现不同判定逻辑
清理资源与防止内存泄漏
ScheduledExecutorService 提交的任务若未完成,可能长期持有对象引用:
- 重试任务执行完毕(无论成功或放弃)后,主动调用
Future.cancel(true)(如果保留了 Future 引用) - 避免在任务中强引用外部大对象(如整个 Service 实例),改用弱引用或仅传必要参数
- 确保 executor 在应用关闭时调用
shutdownNow()并 awaitTermination
这套机制不依赖 Spring Retry 或第三方库,轻量可控,适合嵌入 SDK、底层通信模块或对延迟敏感的中间件逻辑。










