Java8新的异步编程方式 CompletableFuture(三)

前面两篇文章已经整理了CompletableFuture大部分的特性,本文会整理完CompletableFuture余下的特性,以及将它跟RxJava进行比较。

3.6 Either

Either 表示的是两个CompletableFuture,当其中任意一个CompletableFuture计算完成的时候就会执行。

方法名描述
acceptEither(CompletionStage<? extends T> other, Consumer<? super T> action)当任意一个CompletableFuture完成的时候,action这个消费者就会被执行。
acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action)当任意一个CompletableFuture完成的时候,action这个消费者就会被执行。使用ForkJoinPool
acceptEitherAsync(CompletionStage<? extends T> other, Consumer<? super T> action, Executor executor)当任意一个CompletableFuture完成的时候,action这个消费者就会被执行。使用指定的线程池
        Random random = new Random();CompletableFuture<String> future1 = CompletableFuture.supplyAsync(()->{try {Thread.sleep(random.nextInt(1000));} catch (InterruptedException e) {e.printStackTrace();}return "from future1";});CompletableFuture<String> future2 = CompletableFuture.supplyAsync(()->{try {Thread.sleep(random.nextInt(1000));} catch (InterruptedException e) {e.printStackTrace();}return "from future2";});CompletableFuture<Void> future =  future1.acceptEither(future2,str->System.out.println("The future is "+str));try {future.get();} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}复制代码

执行结果:The future is from future1 或者 The future is from future2。
因为future1和future2,执行的顺序是随机的。

applyToEither 跟 acceptEither 类似。

方法名描述
applyToEither(CompletionStage<? extends T> other, Function<? super T,U> fn)当任意一个CompletableFuture完成的时候,fn会被执行,它的返回值会当作新的CompletableFuture<U>的计算结果。
applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T,U> fn)当任意一个CompletableFuture完成的时候,fn会被执行,它的返回值会当作新的CompletableFuture<U>的计算结果。使用ForkJoinPool
applyToEitherAsync(CompletionStage<? extends T> other, Function<? super T,U> fn, Executor executor)当任意一个CompletableFuture完成的时候,fn会被执行,它的返回值会当作新的CompletableFuture<U>的计算结果。使用指定的线程池
        Random random = new Random();CompletableFuture<String> future1 = CompletableFuture.supplyAsync(()->{try {Thread.sleep(random.nextInt(1000));} catch (InterruptedException e) {e.printStackTrace();}return "from future1";});CompletableFuture<String> future2 = CompletableFuture.supplyAsync(()->{try {Thread.sleep(random.nextInt(1000));} catch (InterruptedException e) {e.printStackTrace();}return "from future2";});CompletableFuture<String> future =  future1.applyToEither(future2,str->"The future is "+str);try {System.out.println(future.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}复制代码

执行结果也跟上面的程序类似。

3.7 其他方法

allOf、anyOf是CompletableFuture的静态方法。

3.7.1 allOf

方法名描述
allOf(CompletableFuture<?>... cfs)在所有Future对象完成后结束,并返回一个future。

allOf()方法所返回的CompletableFuture,并不能组合前面多个CompletableFuture的计算结果。于是我们借助Java 8的Stream来组合多个future的结果。

        CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "tony");CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "cafei");CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> "aaron");CompletableFuture.allOf(future1, future2, future3).thenApply(v ->Stream.of(future1, future2, future3).map(CompletableFuture::join).collect(Collectors.joining(" "))).thenAccept(System.out::print);复制代码

执行结果:

tony cafei aaron复制代码

3.7.2 anyOf

方法名描述
anyOf(CompletableFuture<?>... cfs)在任何一个Future对象结束后结束,并返回一个future。
        Random rand = new Random();CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(rand.nextInt(1000));} catch (InterruptedException e) {e.printStackTrace();}return "from future1";});CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(rand.nextInt(1000));} catch (InterruptedException e) {e.printStackTrace();}return "from future2";});CompletableFuture<String> future3 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(rand.nextInt(1000));} catch (InterruptedException e) {e.printStackTrace();}return "from future3";});CompletableFuture<Object> future =  CompletableFuture.anyOf(future1,future2,future3);try {System.out.println(future.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}复制代码

使用anyOf()时,只要某一个future完成,就结束了。所以执行结果可能是"from future1"、"from future2"、"from future3"中的任意一个。

anyOf 和 acceptEither、applyToEither的区别在于,后两者只能使用在两个future中,而anyOf可以使用在多个future中。

3.8 CompletableFuture异常处理

CompletableFuture在运行时如果遇到异常,可以使用get()并抛出异常进行处理,但这并不是一个最好的方法。CompletableFuture本身也提供了几种方式来处理异常。

3.8.1 exceptionally

方法名描述
exceptionally(Function fn)只有当CompletableFuture抛出异常的时候,才会触发这个exceptionally的计算,调用function计算值。
        CompletableFuture.supplyAsync(() -> "hello world").thenApply(s -> {s = null;int length = s.length();return length;}).thenAccept(i -> System.out.println(i)).exceptionally(t -> {System.out.println("Unexpected error:" + t);return null;});复制代码

执行结果:

Unexpected error:java.util.concurrent.CompletionException: java.lang.NullPointerException复制代码

对上面的代码稍微做了一下修改,修复了空指针的异常。

        CompletableFuture.supplyAsync(() -> "hello world").thenApply(s -> {
//                    s = null;int length = s.length();return length;}).thenAccept(i -> System.out.println(i)).exceptionally(t -> {System.out.println("Unexpected error:" + t);return null;});复制代码

执行结果:

11复制代码

3.8.2 whenComplete

whenComplete 在上一篇文章其实已经介绍过了,在这里跟exceptionally的作用差不多,可以捕获任意阶段的异常。如果没有异常的话,就执行action。

        CompletableFuture.supplyAsync(() -> "hello world").thenApply(s -> {s = null;int length = s.length();return length;}).thenAccept(i -> System.out.println(i)).whenComplete((result, throwable) -> {if (throwable != null) {System.out.println("Unexpected error:"+throwable);} else {System.out.println(result);}});复制代码

执行结果:

Unexpected error:java.util.concurrent.CompletionException: java.lang.NullPointerException复制代码

跟whenComplete相似的方法是handle,handle的用法在上一篇文章中也已经介绍过。

四. CompletableFuture VS Java8 Stream VS RxJava1 & RxJava2

CompletableFuture 有很多特性跟RxJava很像,所以将CompletableFuture、Java 8 Stream和RxJava做一个相互的比较。

composablelazyresuableasynccachedpushback pressure
CompletableFuture支持不支持支持支持支持支持不支持
Stream支持支持不支持不支持不支持不支持不支持
Observable(RxJava1)支持支持支持支持支持支持支持
Observable(RxJava2)支持支持支持支持支持支持不支持
Flowable(RxJava2)支持支持支持支持支持支持支持

五. 总结

Java 8提供了一种函数风格的异步和事件驱动编程模型CompletableFuture,它不会造成堵塞。CompletableFuture背后依靠的是fork/join框架来启动新的线程实现异步与并发。当然,我们也能通过指定线程池来做这些事情。

CompletableFuture特别是对微服务架构而言,会有很大的作为。举一个具体的场景,电商的商品页面可能会涉及到商品详情服务、商品评论服务、相关商品推荐服务等等。获取商品的信息时(/productdetails?productid=xxx),需要调用多个服务来处理这一个请求并返回结果。这里可能会涉及到并发编程,我们完全可以使用Java 8的CompletableFuture或者RxJava来实现。

先前的文章:
Java8新的异步编程方式 CompletableFuture(一)
Java8新的异步编程方式 CompletableFuture(二)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/287457.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

情人节,我表白了CSDN小姐姐后,竟然...【为表白写了一个绘图工具,让我不再手残】

情人节&#xff0c;我表白了CSDN小姐姐后&#xff0c;竟然…竟然有人看了这篇文。 以下图片素材由一个还没写完的工具绘制&#xff0c;稍后会放在CSDN的代码仓库&#xff08;现在能用了&#xff0c;还没时间改&#xff0c;颜色填充算法还没写&#xff0c;有能力的朋友可以修改一…

【小程序】刘一哥课堂随机点名提问神器V1.0(附源程序)

为了能让我们的孩子们尽量来教室上课,增强课堂的参与度,激发课堂激情,提高学习效率,一哥也是煞费苦心,于是开发出了这么一款课堂点名提问神器,跟大家分享一下。 打开神器,看到的界面是这样子的,我很感激有勇气按时起床并能到教室的每一位有志之士。 点击【开始】按钮,…

org.hibernate.HibernateException: No Session found for current thread

spring、springmvc和hibernate整合 在sessionFactory.getCurrentSession()时&#xff0c;出现以下异常 No Session found for current thread但使用sessionFactory.openSession()是没有任何问题的 严重: Servlet.service() for servlet [springDispatcherServlet] in context w…

java mysbatis select_MyBatis SELECT基本查询实现方法详解

1、返回一个LISTselect * from tbl_employee where last_name like #{lastName}2、将查询记录封装为一个Mapselect * from tbl_employee where id#{id}返回一条记录的map&#xff1b;key就是列名&#xff0c;值就是对应的值。3、多条记录封装为一个mapMapKey("id")pu…

Git之怎么通过命令修改前面几次提交的记录

1 问题 我们平时用gitlab,github发现提交代码上库记录写错了&#xff0c;需要修改回来。 2 解决办法

Git客户端TortoiseGit(Windows系统)的使用方法

本文环境&#xff1a; 操作系统&#xff1a;Windows XP SP3 Git客户端&#xff1a;TortoiseGit-1.8.8.0-32bit 一、安装Git客户端 全部安装均采用默认&#xff01; 1. 安装支撑软件 msysgit: https://code.google.com/p/msysgit/downloads/list?qfullinstallerofficialgit 当前…

.Net 在容器中操作宿主机

1方案描述 在 docker 容器中想操作宿主机&#xff0c;一般会使用 ssh 的方式&#xff0c;然后 .Net 通过执行远程 ssh 指令来操作宿主机。本文将使用 交互式 .Net 容器版 中提供的镜像演示 .Net 在容器中如何操作宿主机。2前期准备 1. 宿主机上生成 ssh key生成 ss…

【看动漫学编程】程序员在异世界生个娃 第1篇:太极村

前言 作者文笔比较水&#xff0c;还请见谅。 以下内容还将使用视频动态漫画表现&#xff0c;剪辑完将会贴出链接。 小说剧情为剧情需要&#xff0c;过渡到知识点&#xff0c;部分篇幅可能没有技术知识点还望谅解。 由于没有经费支持&#xff0c;所以画出来的东西是我自己用代码…

【ArcGIS风暴】最牛逼空间数据批处理神器来了:用户自定义工具箱GeoStorm.tbx

【Warming up】在学习和工作的过程中,作者曾写过很多采用ArcGIS模型构建器(Model Builder)、Python代码等批处理方法(感兴趣的GISers可以去【测绘地理信息Big风暴专】栏去交流学习指导),大大的减轻了操作压力,提高了工作效率。今天给大家展示一款神器:自定义工具箱GeoS…

2.6. PostgreSQL表之间连接

到目前为止&#xff0c;我们的查询一次只访问了一个表。查询可以一次访问多个表&#xff0c;或者用某种方式访问一个表&#xff0c;而同时处理该表的多个行。一个同时访问同一个或者不同表的多个行的查询叫连接查询。举例来说&#xff0c;比如你想列出所有天气记录以及这些记录…

Android之Caused by: java.lang.IllegalArgumentException: Failed to find configured root that contains

1 问题 用takePhoto去照相的时候特么的一打开就报这个错误 2020-04-09 21:33:49.124 19016-19016/com.appsinnova.android.keepshare E/AndroidRuntime: FATAL EXCEPTION: mainProcess: com.appsinnova.android.keepshare, PID: 19016java.lang.RuntimeException: Unable to …

Linux下c/c++项目代码覆盖率的产生方法

最近做了一系列的单元测试相关的工作&#xff0c;除了各种规范及测试框架以外&#xff0c;讨论比较多的就是关于代码覆盖率的产生&#xff0c;c/c与其他的一些高级语言或者脚本语言相比较而言&#xff0c;例如 Java、.Net和php/python/perl/shell等&#xff0c;由于没有这些高级…

C# WPF从后台代码生成行列可变的表格

z概述WPF常用的表格控件是DataGrid&#xff0c;这个控件在前台XAML编写的话&#xff0c;一般列已经固定&#xff0c;然后给每个列去绑定数据&#xff0c;但是如果我的列不固定&#xff0c;随着运算结果变动呢&#xff1f;这时候DataGrid&#xff0c;就比较难实现这个需求&#…

软件架构实践文章链接

2019独角兽企业重金招聘Python工程师标准>>> 架构 InfoQ: 又拍网架构中的分库设计 SNS网站数据库技术分析 - 51CTO.COM 数据库水平切分的实现原理解析 - iBATIS - Java - JavaEye论坛 基于amoeba的mysql分布式数据库学习&#xff08;一&#xff09; - Java - JavaEy…

【看动漫学编程】程序员在异世界生个娃 第2篇:外挂已准备就绪

前言 作者文笔比较水&#xff0c;还请见谅。 以下内容还将使用视频动态漫画表现&#xff0c;剪辑完将会贴出链接。 小说剧情为剧情需要&#xff0c;过渡到知识点&#xff0c;部分篇幅可能没有技术知识点还望谅解。 由于没有经费支持&#xff0c;所以画出来的东西是我自己用代码…

java剪切txt文件_用Java把剪切板的内容实时保存到txt

test类&#xff1a;提示用户程序已启动&#xff0c;提示保存位置&#xff0c;清空剪切板。package com.ariya.service;import com.ariya.service.impl.ClipboardServiceImpl;/*** author Ariya* 程序入口*/public class Test {public static void main(String[] args) {Clipboa…

【三维激光扫描】第一章:三维激光扫描入门基础知识

随着地理空间信息服务产业的快速发展,地理空间数据的要求越来越高。对地理空间数据的要求正朝着大信息量、高精度、可视化和可挖掘方向发展。地面激光雷达技术是一门新兴的测绘技术,已逐渐成为广大科研和工程技术人员全新的解决问题的手段。地面三维激光扫描技术与全站仪测量…

Android之kotlin里面本地图片BitmapFactory.decodeFile转bitmap失败问题

1 问题 我们手机本地有个图片文件比如如下 /storage/emulated/0/Android/data/package_name/cache/1586444511539.png 我们需要png转bitmap&#xff0c;然后设置到ImageView里面显示 var bitmap BitmapFactory.decodeFile(imagePath);if (bitmap null) returnelse mImagevi…

3、面向对象-继承-多态

1、继承子类可以继承父类的一切&#xff0c;一个子类只能有一个父类&#xff0c;一个父类可以有多个子类//父类class Ren{public $name;public $sex;public $yuyan;function Say() {echo $this->name."正在讲话&#xff01;";}}//美国人的子类class America ex…

整理iOS9适配中出现的坑

一、NSAppTransportSecurity iOS9让所有的HTTP默认使用了HTTPS&#xff0c;原来的HTTP协议传输都改成TLS1.2协议进行传输。直接造成的情况就是App发请求的时候弹出网络无法连接。解决办法就是在项目的info.plist 文件里加上如下节点&#xff1a; NSAppTransportSecurity - NSAl…