一、线程池
核心参数
- corePoolSize 核心线程池大小
- maximumPoolSize 线程池能创建线程的最大数量
- keepAliveTime 空闲线程存活时间
- workQueue 阻塞队列
- handler 饱和策略
execute方法提交任务后,执行逻辑
- 小于核心线程数,创建新线程
- 阻塞队列未满,入队
- 线程池未满,创建
- 按饱和策略处理
二、对比Future
特点
- 支持回调通知
- Future需不断轮询判断任务是否结束
- 便于将不同异步操作组合
- Future编排回调存在回调地狱问题
三、简单使用
3.1 创建
通过静态方法创建实例
- runAsync 无返回值
- supplyAsync 有返回值
CompletableFuture.runAsync(Runnable);
CompletableFuture.runAsync(Runnable, Executor);
CompletableFuture.supplyAsync(Supplier<U>);
CompletableFuture.supplyAsync(Supplier<U>, Executor);
3.2 依赖单个任务
3.2.1 顺序执行
- thenRun 无入参,无返回值
- thenAccept 有入参,无返回值
- thenApply 有入参,有返回值
CompletableFuture.supplyAsync(() -> "request").thenRun(() -> {});
CompletableFuture.supplyAsync(() -> "request").thenAccept(request -> {});
CompletableFuture.supplyAsync(() -> "request").thenRun(request -> "print --> " + request);
3.2.2 异常处理
两种方式 exceptionally 和 handle
3.3 依赖多个任务
3.3.1 and
- thenAfterBoth 无入参,无返回
- thenAcceptBoth 有入参,无返回
- thenCombine 有入参,有返回
cfA.runAfterBoth(cfB, () -> {});
cfA.tehnAcceptBoth(cfB, (A, B) -> {});
cfA.tehnAcceptBoth(cfB, (A, B) -> A + B);
静态方法 allOf 等待多个任务都完成,无返回值
CompletableFuture.allOf(cfA, cfB, cfC)
3.3.2 or
- runAfterEither 无入参,无返回
- acceptEither 有入参,无返回
- applyToEither 有入参,有返回
cfA.runAfterEither(cfB, () -> {});
cfA.tehnAcceptEither(cfB, req -> {});
cfA.tehnAcceptEither(cfB, req -> "req: " + req);
静态方法 anyOf 等待任一任务完成,返回类型为Object
CompletableFuture.anyOf(cfA, cfB, cfC)
四、基本原理
CompletableFuture 有两个核心字段
- result 存当前CompletableFuture的结果
- Completion 存依赖动作
不同CompletableFuture 如何编排起来?
- CompletableFuture 为 被观察者,Completion为 观察者
- 当CompletableFuture完成后,通过postComplete方法通知Completion
- 形象上讲,这种机制 在 不同CompletableFuture节点 间 添加了 边
五、注意事项
5.1 有无Async后缀
不带Async后缀的方法
- 如果注册时被依赖的操作已经执行完成,则由当前线程执行
- 如果注册时被依赖的操作还未执行完,则由回调线程执行
带Async后缀的方法
- 运行在指定线程池Executor
- 当不传递Executor时,会使用ForkJoinPool中的共用线程池CommonPool
5.2 thenCompose
和thenCombine对比
- 都是聚合任务
- combine聚合结果,compose把多个cf实例组合成一个整体
和thenApply对比
- thenApply接收的函数返回一个具体的值,thenCompose接收的函数返回一个新的cf实例
- thenApply是同步,thenCompose是异步