深入理解 Future, CompletableFuture, ListenableFuture,回调机制
本文禁止转载。
本文从设计思想、详细实现等角度分析了 Future、CompletableFuture、ListenableFuture等接口或类,提出了一些最佳实践,英华内容为示例代码。耐心看完,相信你一定会有所收获。文章首发公众号,欢迎关注。
理想的 Future
- 函数式思想:值类型,和类型,结果延迟获取,最终状态有两种,正常获取结果 v 大概异常结果 ex。
- 只有读逻辑,写逻辑由其他类实现(如 Scala 中的 Promise)
- 支持回调,链式调用
- 对异步支持良好,但是也支持同步调用
- 可取消任务,取消的结果视为异常结果
现实的 Future 接口
- Future 封装了任务(写逻辑),提供了阻塞 get()方法,但是结果为四种状态,而且是以受检异常形式抛出,每次处置处罚时都必要 try-catch,无法分别处置处罚。受检异常的题目是即使知道代码不会抛异常,还是要写模版代码 catch 处置处罚。
- V get() throws InterruptedException, ExecutionException;
- V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
复制代码
- 非逼迫的取消任务机制,调用 cancel 方法,若任务处于 NEW 状态,可以保证取消;若任务处于运行状态,必要依赖于任务支持停止机制,Java 的停止机制是设立标志位,无法直接传输数据。
- boolean cancel(boolean mayInterruptIfRunning);
复制代码
- Future 接口不支持回调以及链式调用,CompletableFuture 实现了此功能,但是自身也有一些题目。
- Future 接口可以当做值类型利用,也推荐这么利用,不过许多情况下会出现对于 Future 结果的修改。note: Java 底层不支持值类型,其值类型官方说法为 value-based。必要注意区分值类型和可变数据容器 Wrapper 类,值类型是不可变的,比如 Integer 和 AtomicInteger 的区别。
- JDK19 的改进
在 JDK19 终于提供了以下一系列方法,其基本思想就是值类型,绕过 get 阻塞调用的弊端。当已知结果已经得出后,直接取值,无需进行受检异常处置处罚。美中不足:停止机制还是不视为异常的一部门,exceptionNow 在停止状态时,还是会停止当前线程。- default V resultNow();
- default Throwable exceptionNow();
- default State state();
- enum State {
- /**
- * The task has not completed.
- */
- RUNNING,
- /**
- * The task completed with a result.
- * @see Future#resultNow()
- */
- SUCCESS,
- /**
- * The task completed with an exception.
- * @see Future#exceptionNow()
- */
- FAILED,
- /**
- * The task was cancelled.
- * @see #cancel(boolean)
- */
- CANCELLED
- }
复制代码 总之,新增的默认方法利用必要先进行状态判定,然后调用获取结果方法。以下是代码示例:- // 处理已运算结果
- results = futures.stream()
- .filter(f -> f.state() == Future.State.SUCCESS)
- .map(Future::resultNow)
- .toList();
- // allOf 运算结果处理
- CompletableFuture.allOf(c1, c2, c3).join();
- foo(c1.resultNow(), c2.resultNow(), c3.resultNow());
复制代码 不过,默认方法对于第三方库来说可能会出现运行题目,必要确认第三方库支持再利用默认方法。
CompletableFuture 大幅改进
岁月史书:Future, ExecutorService, BlockingQueue, AQS 等在 JDK1.5 推出,随后 Google Guava 类库提供了 ListenableFuture 补全了 Future 的回调功能,CompletableFuture 鉴戒了 ListenableFuture 功能,联合函数式支持,在 JDK1.8 推出。
1. 链式调用
- public class CompletableFuture<T> implements Future<T>, CompletionStage<T>
复制代码 大部门链式调用方法界说在 CompletionStage 中:
[table][tr]CompletionStage 接口方法函数式接口Stream 相似方法[/tr][tr][td]<U> CompletionStage<U> thenApply(Function |