再谈CompletableFuture
条评论今天是还之前欠的一个账,当时在Vert.x异步方法转同步这篇文章里,我提到其关键点是CompletableFuture类,今天我们就沿着当时的代码继续掰扯一下这个强大的类。
先来回顾下当时的代码
| import io.vertx.core.Vertx | 
vertx.setTimer是个先天异步的东西,我们让它来模拟一个异步调用,你可以想象成从网络、磁盘或者其他什么接口,获取到那么一个字符串hello world。这么一个过程是异步的。然后在一个非异步程序的大环境下,后续的程序要等待这么一个结果。
此时我们用到了CompletableFuture,并且牵扯到其中的两个方法:complete(T value)、get()。
complete(T value)
| If not already completed, sets the value returned by get() and related methods to the given value. | 
这个很好理解,就是给completableFuture塞一个完成的结果,供后续的方法调用获取,最典型的就是get()
get()
| Waits if necessary for this future to complete, and then returns its result. | 
这个get()方法源自于Future接口,是一个早在Java 1.5时代就提供的接口了。这个方法就是典型的阻塞式获取Future结果。放在上面的代码里,恰好能起到把vert.x的异步调用转换成同步的效果。但其实着不是什么好事,在Java 8中特意引入CompletableFuture就是为了解决阻塞问题,让异步发挥出更大的优势。
发散一下
抛开上面有意把异步转同步不说,我们来看看如果借助CompletableFuture,把vert.x的异步跟Java 8的异步有效结合,尝试代码如下:
| import io.vertx.core.Vertx | 
简单改造过后,这就是一个遵循Java 8中CompletableFuture风格的异步使用方式。关键点在于whenCompleteAsync(@NotNull BiConsumer<? super T, ? super Throwable> action)
方法,同时还有whenComplete(@NotNull BiConsumer<? super T, ? super Throwable> action)
方法可供使用。这两个方法最大的区别是,前者会为action的执行上下文准备ForkJoinPool线程池环境;而后者会让action使用之前completableFuture.complete()所处的线程上下文。
CompletableFuture是一个异常强大且复杂的类,本文所讲的东西不过是九牛一毛。这里推荐两个不错的帖子供大家参考:
- https://www.ibm.com/developerworks/cn/java/j-cf-of-jdk8/index.html - 其中第二篇文章涉及的代码,我已经整理了一份,你可以从这里获取gist 
本文标题:再谈CompletableFuture
文章作者:牧云踏歌
发布时间:2018-09-12
最后更新:2018-09-12
原始链接:http://www.kankanzhijian.com/2018/09/12/CompletableFuture_something/
版权声明:本博客文章均系本人原创,转载请注名出处