转载

Java 8 的这个新特性,你用了吗?

Java 8 的这个新特性,你用了吗?

本文阅读时间大约6分钟。

前段时间工作上比较忙,这篇文章一直没来得及写,本文是阅读《Java8实战》的时候,了解到Java 8里已经提供了一个异步非阻塞的接口(CompletableFuture),可以实现简单的响应式编程的模式,因此用这篇文章做个梳理。我是带着下面这几个问题去学习CompletableFuture这个接口的。

  1. CompletableFuture是为了解决什么问题而设计的?

  2. 它的使用场景是什么?开源软件中有实战使用案例吗?

  3. CompletableFuture的常用API都有哪些?如何使用?

  4. CompletableFuture和RxJava有什么不同?

这篇文章梳理下来,基本上可以回答前面四个问题,OK,我们进入正文。

Java 8 的这个新特性,你用了吗?

基本概念

Java 8 的这个新特性,你用了吗?

如上图所示,RPC(远程方法调用)的四种方式有:oneway、sync、future和callback,在dubbo或bolt这类通信框架中,默认使用的是sync模式(同步+阻塞),future和callback都属于异步模式,不过future模式在get的时候会阻塞,callback模式则不需要等待结果,有结果后服务端会回调请求方。

异步调用这类模式,比较适合的场景是IO密集型场景,要执行很多远程调用的任务,并且这些调用耗时可能比较久。以openwrite中的一个case为例:我发布一篇文章,需要给几个不同的写作平台创建文章,这时候我不希望这个过程是顺序的,就比较适合用异步调用模式。

Future模式除了在get()调用的时候会阻塞外,还有其他的局限性,例如:没有使用Java Lambda表达式的优势,对一连串的异步调用可以支持,但是写出来的代码会比较复杂。

Java 8 的这个新特性,你用了吗?

CompletableFuture的常用API

阅读CompletableFuture的API的时候,我有一个体会——CompletableFuture之于Future,除了增加了回调这个最重要的特性,其他的特性有点像Stream对于集合迭代的增强。

使用CompletableFuture,我们可以像Stream一样使用异步调用,可以处理一些级联的异步调用(类似于Stream里的flatMap)、可以过滤一些无用的异步调用(anyOf、allOf)。

下面这张图是我按照自己的理解,梳理除了CompletableFuture常见的API,阅读的时候需要注意下面几个点:

  1. 把握几个大的分类:创建CompletableFuture、获取CompletableFuture的执行结果、主动结束CompletableFuture、异步调用任务的组合处理;

  2. 看着方法多,但是有规律可循,例如apply字样的接口,传入的方法参数都是有返回值的;

  3. 带either字样的,都是多个异步任务有一个满足条件即可的;

  4. 带executor方法的,都表示该方法可以用自定义的线程池来优化性能。

  5. 关注公众号:javaadu,回复关键词CompletableFuture,可以获取下图的xmind文件

Java 8 的这个新特性,你用了吗?

Java 8 的这个新特性,你用了吗?

Dubbo项目中的使用案例

Dubbo对于异步化的支持起始在2.6.x中就有提供,是在发布bean的时候加个属性配置——async=true,然后利用上下文将异步标识一层层传递下去。在之前的公司中有一次排查dubbo(当时我们用的是dubbox)异步调用的问题,最后查到的原因就是多个异步调用,上下文里的信息串了。

Dubbo 2.7 中使用了JDK1.8 提供的 CompletableFuture 原生接口对自身的异步化做了改进。CompletableFuture 可以支持 future 和 callback 两种调用方式。在Dubbo最新的master代码中,我知道了Dubbo的异步结果的定义,它的类图如下,可以看出AsyncRpcResult是一个CompletableFuture接口的实现。

Java 8 的这个新特性,你用了吗?

实战Demo

通过下面的例子,可以看出CompletableFuture的最大好处——callback特性。 首先定义一个接口,其中包括同步接口和该接口的异步版本。

Java 8 的这个新特性,你用了吗?

然后定义该接口的实现类,可以看出,如果要讲现有的同步接口异步化,是比较容易的;

Java 8 的这个新特性,你用了吗?

然后看下我们的测试case,如下:

Java 8 的这个新特性,你用了吗?

上面这个案例的执行结果如下图所示,第一行是顺序执行的结果,第二行是使用了异步回调执行的结果。可以看出,如果不使用一部回调特性,整体的时间就是每部分工作的总和,但是如果使用异步回调来将一部分工作时间重合掉,就可以尽可能得快速完成工作。

Java 8 的这个新特性,你用了吗?

Java 8 的这个新特性,你用了吗?

参考资料

  1. Dubbo中的新特性

    http://dubbo.apache.org/zh-cn/blog/dubbo-27-features.html

  2. 怎么理解同步、异步和阻塞、非阻塞?

    https://www.zhihu.com/question/19732473/answer/20851256

  3. 《Java 8实战》

Java 8 的这个新特性,你用了吗?

下方查看 历史 文章

【译】深入理解G1的GC日志(一)

使用Optional摆脱NPE的折磨

MySQL单表数据不要超过500万行:是经验数值,还是黄金铁律?

面试官:讲讲redis的过期策略如何实现?

Java 8 的这个新特性,你用了吗?

本号专注于后端技术、JVM问题排查和优化、Java面试题、个人成长和自我管理等主题,为读者提供一线开发者的工作和成长经验,期待你能在这里有所收获。关注后,记得回复关键词获取独家技术资料哦。

Java 8 的这个新特性,你用了吗?

我就知道你“在看”

Java 8 的这个新特性,你用了吗?

原文  https://mp.weixin.qq.com/s/252Uay68lH39sGh80rnbGg
正文到此结束
Loading...