CompletableFuture 吞掉的异常去哪了
一次线上问题:订单支付成功后,异步任务负责发通知、写积分、更新报表。上线第二天,有用户反馈没收到通知,但日志干干净净,监控也没报错,任务看起来“成功”了。
最后定位到一行代码:CompletableFuture 里的异常,没有人接。
一个没有堆栈的失败
先看最小复现:
[ CATEGORY ]
java 分类下共有 2 篇编程实战文章,涵盖常见问题排查、代码示例与实践经验。
一次线上问题:订单支付成功后,异步任务负责发通知、写积分、更新报表。上线第二天,有用户反馈没收到通知,但日志干干净净,监控也没报错,任务看起来“成功”了。
最后定位到一行代码:CompletableFuture 里的异常,没有人接。
先看最小复现:
很多人第一次配置线程池,是照着某篇博客写下 new ThreadPoolExecutor(10, 20, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<>())。上线后一切正常,直到流量翻倍:接口 P99 从 80ms 涨到 3 秒,堆内存一路爬升,Full GC 之后也回不到原来的水位。
线程池只有七个构造参数,但它们彼此耦合。下面从“线程池到底什么时候创建线程”讲起,再说三个最常见的坑。
ThreadPoolExecutor.execute() 的判断顺序是固定的,记住这四步,后面所有问题都能推出来: