# CompletableFuture ## 为什么要引入 CompletableFuture - Future.get() 方法会阻塞线程,一直阻塞,直到其所对应的任务完成或因为异常退出。在不恰当的地方调用此方法会因为线程阻塞而降低系统响应度。就像文中提到的。 - Future.get(long, TimeUnit) 可以一定的时间内超时退出,而不会像前一个方法那样一直阻塞线程。但是这对系统响应性的改进是治标不治本。 - Java 8 引入了 CompletableFuture,可用通过 CompletableFuture thenAccept(Consumer action) 方法异步触发 send(Response) 方法。这时 serve() 方法会很快结束。而当 responseFuture 所对应的任务完成时,send(Response) 方法便会被调用,其执行线程同 responseFuture 所对应的任务的执行线程相同。 - 对于上一点,有人会问,何必这么麻烦?直接在 responseFuture 所对应任务 (Runnable or Callable) 里面调用 send(Response) 方法。各种在实际工作中可能会遇到的问题暂且不说。只说两点: 1. responseFuture 所对应任务是不可修改的,比如调用自第三方模块 2. 即便代码可修改,但在 responseFuture 所对应的任务中去调用 send(Response) 方法表明的含义是后者的功能从属于前者。这可能从业务角度上看是不合理的。即在本例中,responseFuture 所对应的任务和 send(Response) 方法在业务角度讲是属于同一级的。违反这一点会对代码可读性和可维护性不利。 ## 创建 CompletableFuture 以下四个静态方法用来为一段异步执行的代码创建 `CompletableFuture` 对象: ```java static CompletableFuture runAsync(Runnable runnable) static CompletableFuture runAsync(Runnable runnable, Executor executor) static CompletableFuture supplyAsync(Supplier supplier) static CompletableFuture supplyAsync(Supplier supplier, Executor executor) ``` 以 `Async` 结尾并且没有指定 `Executor` 的方法会使用 `ForkJoinPool.commonPool()` 作为它的线程池执行异步代码。 ## 计算结果完成时的处理 当 `CompletableFuture` 的计算结果完成,或者抛出异常的时候,我们可以执行特定的 `Action`。 ```javap CompletableFuture whenComplete(BiConsumer action) CompletableFuture whenCompleteAsync(BiConsumer action) CompletableFuture whenCompleteAsync(BiConsumer action, Executor executor) CompletableFuture exceptionally(Function fn) ``` 同时进行计算和转换 ```java CompletableFuture handle(BiFunction fn) CompletableFuture handleAsync(BiFunction fn) CompletableFuture handleAsync(BiFunction fn, Executor executor) ``` ## 结果转换(map) ```java CompletableFuture thenApply(Function fn) CompletableFuture thenApplyAsync(Function fn) CompletableFuture thenApplyAsync(Function fn, Executor executor) ``` ## flatMap ```java CompletableFuture thenCompose(Function> fn) CompletableFuture thenComposeAsync(Function> fn) CompletableFuture thenComposeAsync(Function> fn, Executor executor) ``` ## 消耗型 ```java CompletableFuture thenAccept(Consumer action) CompletableFuture thenAcceptAsync(Consumer action) CompletableFuture thenAcceptAsync(Consumer action, Executor executor) ``` `thenAccept(Consumer action)` 这个方法的命名采用了类似 Promise 的命名风格。 如果把这个方法命名为 addListener 会更容易理解,但是命名为 addListener 不能体现出 thenAccept 能返回 CompletableFuture 从而形成链式调用的特点。 当两个 `CompletionStage` 都正常完成计算的时候,执行一个 `Runnable` ```java CompletableFuture thenAcceptBoth(CompletionStage other, BiConsumer action) CompletableFuture thenAcceptBothAsync(CompletionStage other, BiConsumer action) CompletableFuture thenAcceptBothAsync(CompletionStage other, BiConsumer action, Executor executor) CompletableFuture runAfterBoth(CompletionStage other, Runnable action) ``` 对上一步的计算结果不关心,执行下一个操作 ```java CompletableFuture thenRun(Runnable action) CompletableFuture thenRunAsync(Runnable action) CompletableFuture thenRunAsync(Runnable action, Executor executor) ``` ## 组合 ```java CompletableFuture thenCombine(CompletionStage other, BiFunction fn) CompletableFuture thenCombineAsync(CompletionStage other, BiFunction fn) CompletableFuture thenCombineAsync(CompletionStage other, BiFunction fn, Executor executor) ``` ## Either ```java CompletableFuture acceptEither(CompletionStage other, Consumer action) CompletableFuture acceptEitherAsync(CompletionStage other, Consumer action) CompletableFuture acceptEitherAsync(CompletionStage other, Consumer action, Executor executor) CompletableFuture applyToEither(CompletionStage other, Function fn) CompletableFuture applyToEitherAsync(CompletionStage other, Function fn) CompletableFuture applyToEitherAsync(CompletionStage other, Function fn, Executor executor) ``` ## allOf、anyOf ```java static CompletableFuture allOf(CompletableFuture... cfs) static CompletableFuture anyOf(CompletableFuture... cfs) ``` [CompletableFuture 的 20 个例子](https://zhuanlan.zhihu.com/p/34921166)