线程池的异常处理 execute() 方法提交任务时,如果任务在执行的过程中出现运行时异常,会导致执行任务的线程终止;不过,最致命的是任务虽然异常了,但是你却获取不到任何通知,这会让你误以为任务都执行得很正常。
最好的办法还是捕获所有异常,按需处理
线程池的使用建议
业务隔离
压测确定队列长度或线程数
核心池大小
经验值
IO密集型
2 * CPU + 1
CPU密集型
CPU + 1
实践值
最佳线程数目 = (线程等待时间与线程CPU时间之比 + 1)* CPU数目
最佳值
压测
线程池流程
笔记
如何获取异步执行结果
Future
CountdownLatch
join方法
Future接口是一个获取异步结果的通用接口
FutureTask是如何获取结果的
FutureTask源码中状态标识 state
NEW = 0;初始状态
COMPLETING = 1;正在执行
NORMAL = 2;
EXCEPTIONAL = 3;
CANCELLED = 4;
INTERRUPTING = 5;
INTERRUPTED = 6;
状态转换 TODO详细阅读源码理解
NEW -> COMPLETING -> NORMAL
NEW -> COMPLETING -> EXCEPTIONAL
NEW -> CANCELLED
NEW -> INTERRUPTING -> INTERRUPTED
FutureTask的阻塞方法不像有些博客说的 Object#wait而是 LockSupport.park(this);对应的唤醒线程的方法 LockSupport.unpark(this);
TODO
总结java中实现获取异步结果的方式和工具
总结 异步转同步的方式
24 | CompletableFuture:异步编程没那么难笔记
CompletableFuture 的核心优势
无需手工维护线程,没有繁琐的手工维护线程的工作,给任务分配线程的工作也不需要我们关注;(对比FutureTask的实现)
语义更清晰,例如 f3 = f1.thenCombine(f2, ()->{}) 能够清晰地表述“任务 3 要等待任务 1 和任务 2 都完成后才能开始”;
代码更简练并且专注于业务逻辑,几乎所有代码都是业务逻辑相关的。
创建CompletableFuture对象
runAsync(Runnable runnable) 不获取返回值的静态方法
supplyAsync(Supplier supplier) 可获取返回值的方法 (ps:作用同Future),Supplier相对于Runnable,get方法可以获取返回值
以上两个方法可以指定线程池 (PS:CompletableFuture默认使用ForkJoinPool线程池)
//使用默认线程池 static CompletableFuture<Void> runAsync(Runnable runnable) static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier) //可以指定线程池 static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor) static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor)CompletableFuture实现的CompletionStage接口的作用
任务的时序关系管理
串行关系
并行关系
汇聚关系
AND汇聚关系CompletionStage<R> thenCombine(other, fn); CompletionStage<R> thenCombineAsync(other, fn); CompletionStage<Void> thenAcceptBoth(other, consumer); CompletionStage<Void> thenAcceptBothAsync(other, consumer); CompletionStage<Void> runAfterBoth(other, action); CompletionStage<Void> runAfterBothAsync(other, action);
OR 汇聚关系
CompletionStage applyToEither(other, fn); CompletionStage applyToEitherAsync(other, fn); CompletionStage acceptEither(other, consumer); CompletionStage acceptEitherAsync(other, consumer); CompletionStage runAfterEither(other, action); CompletionStage runAfterEitherAsync(other, action);