CompletableFuture避坑1——需要自定义线程池
CompletableFuture避坑2——allOf()超时时间不合理的后果
CompletableFuture避坑3——线程池的DiscardPolicy()导致整个程序卡死
CompletableFuture处理多线程任务时一般建议自定义线程池,线程池有个容量满了的处理策略:
- ThreadPoolExecutor.DiscardPolicy()
- ThreadPoolExecutor.DiscardOldestPolicy()
- ThreadPoolExecutor.AbortPolicy()
- ThreadPoolExecutor.CallerRunsPolicy()
分别对应: - 丢弃新提交的任务
- 丢弃等待中的最早的任务
- 抛异常,RejectedExecutionException
- 线程池不接任务,由提交任务的线程自己执行
也可以自己实现RejectedExecutionHandler
接口:
new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
log.error("xxx");
throw new RuntimeException();
}
});
可以抛出异常,可以忽略,也可以做其他处理。
用子线程执行有兜底策略的任务(例如执行失败了使用默认数据等)时,如果线程池满了,我们经常会设置为打日志(不报警也不抛异常),统计失败数量,失败数量在一定范围内则忽略影响。这在以前是没问题的。
开始使用jdk8的新API CompletableFuture 之后,CompletableFuture.allOf()
方法或者get()
方法等待所有CompletableFuture执行完时,如果采用丢弃策略(包括自定义的不抛异常),则allOf()方法和get()方法会无限期的等待下去,即使allof()设置了orTimeout(2000, TimeUnit.MILLISECONDS)
、get()使用get(2000, TimeUnit.MILLISECONDS)
也不会超时结束。