线程池拒绝策略执行之后的补偿案例
1. 重试机制补偿
在拒绝策略中捕获异常后,通过循环重试将任务重新加入队列,适合对实时性要求不高的场景。
import java.util.concurrent.*;public class RetryPolicyExample {public static void main(String[] args) {ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 60, TimeUnit.SECONDS,new ArrayBlockingQueue<>(2),new ThreadPoolExecutor.AbortPolicy() // 默认策略);Runnable task = () -> System.out.println("任务执行中...");// 重试逻辑for (int i = 0; i < 3; i++) { // 最多重试3次try {executor.execute(task);break; // 成功则退出循环} catch (RejectedExecutionException e) {System.err.println("任务被拒绝,尝试第" + (i + 1) + "次重试");try { Thread.sleep(1000); } catch (InterruptedException ie) { ie.printStackTrace(); }}}executor.shutdown();}
}
此代码在任务被拒绝时休眠1秒后重试,避免频繁请求导致系统过载。
2. 降级处理补偿
当重试失败时,可执行降级逻辑(如记录日志、返回默认值或异步存储任务)。
示例:电商订单支付失败后调用补偿接口退款。
public class PaymentTask implements Runnable {@Overridepublic void run() {try {processPayment(); // 模拟支付} catch (Exception e) {compensatePayment(); // 调用补偿}}private void compensatePayment() {System.out.println("支付失败,执行补偿:退款至用户账户");}
}
通过实现Runnable
的任务内部捕获异常并触发补偿逻辑,适用于必须保证最终一致性的场景。
3. 备用线程池接管
主线程池满时,将任务提交到备用线程池或单线程池兜底。
Service backupExecutor = Executors.newSingleThreadExecutor();ThreadPoolExecutor mainExecutor = new ThreadPoolExecutor(2, 2, 0, TimeUnit.SECONDS,new SynchronousQueue<>(),(r, executor) -> backupExecutor.execute(r) // 自定义拒绝策略
);
通过自定义拒绝策略将任务转发到备用线程池,避免任务丢失。
4. 持久化存储
将拒绝的任务持久化到数据库或消息队列,后续异步处理。
示例代码片段:
rejectedExecutionHandler = (r, executor) -> {saveToDatabase(r); // 存储任务到数据库System.out.println("任务已持久化,等待恢复");
};
关键点总结
补偿方法 | 适用场景 | 优势与风险 |
---|---|---|
重试机制 | 临时性资源不足 | 简单易实现,但可能加重系统负担 |
降级处理 | 必须保证最终一致性的业务 | 避免业务中断,但需设计补偿逻辑 |
备用线程池 | 高优先级任务 | 资源隔离,但增加复杂度 |
持久化存储 | 允许延迟处理的批量任务 | 可靠性高,但引入额外存储依赖 |
注:实际选择需结合业务容忍度和系统资源情况