CompletableFuture详解~CompletionStage

CompletableFuture 分别实现两个接口 FutureCompletionStage

Future 接口大家都比较熟悉,这里主要讲讲 CompletionStage

CompletableFuture 大部分方法来自CompletionStage 接口,正是因为这个接口,CompletableFuture才有如此强大功能。

想要理解 CompletionStage 接口,我们需要先了解任务的时序关系的。我们可以将任务时序关系分为以下几种:

  • 串行执行关系

  • 并行执行关系

  • AND 汇聚关系

  • OR 汇聚关系

1.串行执行关系

任务串行执行,下一个任务必须等待上一个任务完成才可以继续执行。

 CompletionStage 有四组接口可以描述串行这种关系,分别为:

// 同步
CompletableFuture<U> thenApply(Function<? super T, ? extends u> fn)
CompletableFuture<Void> thenAccept(Consumer<? super T> action)
CompletableFuture<Void> thenRun(Runnable action)
// 这个比较特殊,类似于Stream.flatmap
CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn)// 异步
CompletionStage<U> thenApplyAsync(Function<? super T, ? extends u> fn)
CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action)
CompletionStage<Void> thenRunAsync(Runnable action)
// 这个比较特殊,类似于Stream.flatmap
CompletionStage<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn)

thenApply 方法需要传入核心参数为 Function<T,R>类型。这个类核心方法为:

 R apply(T t)

所以这个接口将会把上一个任务返回结果当做入参,执行结束将会返回结果。

thenAccept 方法需要传入参数对象为 Consumer<T>类型,这个类核心方法为:

void accept(T t)

返回值 void 可以看出,这个方法不支持返回结果,但是需要将上一个任务执行结果当做参数传入。

thenRun 方法需要传入参数对象为 Runnable 类型,这个类大家应该都比较熟悉,核心方法既不支持传入参数,也不会返回执行结果。

thenCompose 方法作用与 thenApply 一样,只不过 thenCompose 需要返回新的  CompletionStage。这么理解比较抽象,可以集合代码一起理解。

CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> "hello,楼下小哥");cf.thenApply(String::toLowerCase);
// 需要重新创建一个CompletionStage
cf.thenCompose(s -> CompletableFuture.supplyAsync(s::toLowerCase));

方法中带有 Async ,代表可以异步执行,这个系列还有重载方法,可以传入自定义的线程池,上图未展示,读者只可以自行查看 API。

最后我们通过代码展示 thenApply 使用方式:

CompletableFuture<String> cf= CompletableFuture.supplyAsync(() -> "hello,楼下小哥")// 1.thenApply(s -> s + "@程序通事") // 2.thenApply(String::toUpperCase); // 3System.out.println(cf.join());
// 输出结果 HELLO,楼下小哥@程序通事

这段代码比较简单,首先我们开启一个异步任务,接着串行执行后续两个任务。任务 2 需要等待任务1 执行完成,任务 3 需要等待任务 2。

上面方法,大家需要记住了  Function<T,R>Consumer<T>Runnable 三者区别,根据场景选择使用。

2.AND 汇聚关系

 

如上所示,只有任务 A 与任务 B 都完成之后,任务 C 才会开始执行。

CompletionStage 有以下接口描述这种关系。

// 同步
CompletableFuture<V> thenCombine(CompletionStage<U> other, BiFunction<T,U,V> fn)
CompletableFuture<Void> thenAcceptBoth(CompletionStage<U> other, BiConsumer<T,U> action)
CompletableFuture<Void> runAfterBoth(CompletionStage<U> other, Runnable action)// 异步
CompletableFuture<V> thenCombineAsync(CompletionStage<U> other, BiFunction<T,U,V> fn)
CompletableFuture<Void> thenAcceptBothAsync(CompletionStage<U> other, BiConsumer<T,U> action)
CompletableFuture<Void> runAfterBothAsync(CompletionStage<U> other, Runnable action)// 多组任务
static CompletableFuture<Void> allOf(CompletableFuture<?>... cfs)

thenCombine 方法核心参数 BiFunction ,作用与 Function一样,只不过 BiFunction 可以接受两个参数,而 Function 只能接受一个参数。

thenAcceptBoth 方法核心参数BiConsumer 作用也与 Consumer一样,不过其需要接受两个参数。

runAfterBoth  方法核心参数最简单,上面已经介绍过,不再介绍。

这三组方法只能完成两个任务 AND 汇聚关系,如果需要完成多个任务汇聚关系,需要使用 CompletableFuture#allOf,不过这里需要注意,这个方法是不支持返回任务结果。

AND 汇聚关系相关示例代码,开头已经使用过了,这里再粘贴一下,方便大家理解:

// 任务1.订购航班
CompletableFuture<String> orderAirplane = CompletableFuture.supplyAsync(() -> {System.out.println("查询航班");sleep(3, TimeUnit.SECONDS);System.out.println("订购航班");return "航班信息";
});// 任务2.订购酒店
CompletableFuture<String> orderHotel = CompletableFuture.supplyAsync(() -> {System.out.println("查询酒店");sleep(5, TimeUnit.SECONDS);System.out.println("订购酒店");return "酒店信息";
});// 任务3.任务1和任务2都完成,才能去订购租车服务
CompletableFuture<String> hireCar = orderHotel.thenCombine(orderAirplane, (airplane, hotel) -> {System.out.println("根据航班和酒店订购租车服务");sleep(5, TimeUnit.SECONDS);return "租车信息";
});// 等待任务3执行结果
System.out.println(hireCar.join());// 执行结果
查询航班
查询酒店
订购航班
订购酒店
根据航班和酒店订购租车服务
租车信息

3.OR 汇聚关系

有 AND 汇聚关系,当然也存在 OR 汇聚关系。OR 汇聚关系代表只要多个任务中任一任务完成,就可以接着接着执行下一任务。

CompletionStage 有以下接口描述这种关系:

// 同步
CompletableFuture<V> applyToEither(CompletionStage<U> other, Function<T,U> fn)
CompletableFuture<Void> acceptEither(CompletionStage<U> other, Consumer<T> action)
CompletableFuture<Void> runAfterEither(CompletionStage<U> other, Runnable action)// 异步
CompletableFuture<V> applyToEitherAsync(CompletionStage<U> other, Function<T,U> fn)
CompletableFuture<Void> acceptEitherAsync(CompletionStage<U> other, Consumer<T> action)
CompletableFuture<Void> runAfterEitherAsync(CompletionStage<U> other, Runnable action)// 多组任务
static CompletableFuture<Void> anyOf(CompletableFuture<?>... cfs)

前面三组接口方法传参与 AND 汇聚关系一致,这里也不再详细解释了。

当然 OR 汇聚关系可以使用 CompletableFuture#anyOf 执行多个任务。

下面示例代码展示如何使用 applyToEither 完成 OR 关系。

CompletableFuture<String> cf= CompletableFuture.supplyAsync(() -> {sleep(5, TimeUnit.SECONDS);return "hello,楼下小哥";
});// 1CompletableFuture<String> cf2 = cf.supplyAsync(() -> {sleep(3, TimeUnit.SECONDS);return "hello,程序通事";
});
// 执行 OR 关系
CompletableFuture<String> cf3 = cf2.applyToEither(cf, s -> s);// 输出结果,由于 cf2 只休眠 3 秒,优先执行完毕
System.out.println(cf2.join());
// 结果:hello,程序通事

 

4.异常处理

CompletableFuture  方法执行过程若产生异常,当调用 getjoin获取任务结果才会抛出异常。

CompletableFuture<Integer> cf = CompletableFuture.supplyAsync(() -> (66/0)).thenApply(r -> r*10);System.out.println(cf.join());// java.util.concurrent.CompletionException:java.lang.ArithmeticException: / by zero

上面代码我们显示使用 try..catch 处理上面的异常。不过这种方式不太优雅,CompletionStage 提供几个方法,可以优雅处理异常。

// 同步
CompletableFuture<T> exceptionally(Function<Throwable, ? extends T> fn)
CompletableFuture<T> whenComplete(BiConsumer<T, ? super Throwable> action)
CompletableFuture<T> handle(BiFunction<T, Throwable, ? extends U> fn)// 异步
CompletableFuture<T> whenCompleteAsync(BiConsumer<T, ? super Throwable> action)
CompletableFuture<T> handleAsync(BiFunction<T, Throwable, ? extends U> fn)

exceptionally 使用方式类似于 try..catch 中 catch代码块中异常处理。

whenComplete 与 handle 方法就类似于 try..catch..finanlly 中 finally 代码块。无论是否发生异常,都将会执行的。这两个方法区别在于  handle  支持返回结果。

下面示例代码展示 handle 用法:

CompletableFuture<Integer>f0 = CompletableFuture.supplyAsync(() -> (7 / 0)).thenApply(r -> r * 10).handle((integer, throwable) -> {// 如果异常存在,打印异常,并且返回默认值if (throwable != null) {throwable.printStackTrace();return 0;} else {// 如果return integer;}});System.out.println(f0.join());
/***java.util.concurrent.CompletionException: java.lang.ArithmeticException: / by zero* .....* * 0*/

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

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

相关文章

Python 异步 IO 、协程、asyncio、async/await、aiohttp

From &#xff1a;廖雪峰 异步IO &#xff1a;https://www.liaoxuefeng.com/wiki/1016959663602400/1017959540289152 Python Async/Await入门指南 &#xff1a;https://zhuanlan.zhihu.com/p/27258289 Python 生成器 和 yield 关键字&#xff1a;https://blog.csdn.net/free…

智能语音简史:这场技术革命从哪开始?

来源&#xff1a;与非网1952年&#xff0c;贝尔实验室&#xff08;Bell Labs&#xff09;制造一台6英尺高自动数字识别机“Audrey”&#xff0c;它可以识别数字0&#xff5e;9的发音&#xff0c;且准确度高达90&#xff05;以上。并且它对熟人的精准度高&#xff0c;而对陌生人…

精益创业~如何驾驭愿景

开发-测量-认知 反馈循环 循环中把总时间缩至最短 要把科学的方法运用到新创企业中&#xff0c;我们必须找到哪些假设是需要测试的。这是新创企业计划中风险最大的部分&#xff0c;这部分内容依赖 信念飞跃 Leap-of-Faith 式的大胆假设。其中最重要的两个假设是 价值假设 和 增…

Python 中 异步协程 的 使用方法介绍

静觅 崔庆才的个人博客&#xff1a;Python中异步协程的使用方法介绍&#xff1a;https://cuiqingcai.com/6160.html Python 异步 IO 、协程、asyncio、async/await、aiohttp&#xff1a;https://blog.csdn.net/freeking101/article/details/85286199 1. 前言 在执行一些 IO 密…

半导体终极武器光刻机:为何中国难望ASML项背?!有了全套图纸也做不出来

来源&#xff1a; XuS风险创投行指甲盖大小的芯片&#xff0c;密布千万电线&#xff0c;纹丝不乱&#xff0c;需要极端精准的照相机——光刻机。光刻机精度&#xff0c;决定了芯片的上限。EUV半导体业的终极武器这全靠总部后头那栋最高机密的巨型厂房&#xff0c;里头身穿无尘衣…

AI 与人类未来

来源&#xff1a;腾讯网摘要&#xff1a;今天的人类学&#xff0c;依托协同进化理论&#xff0c;对AI充满信心。 社会产生前后&#xff0c;人类遭遇的进化机制不同。产生之前&#xff0c;是纯粹生态的进化机制&#xff0c;由偶然性和适应性控制&#xff0c;由创造性进化的跃迁…

试玩C++ 操作页面控件

最近数字和金山吵的热火朝天的&#xff0c;群里有人说网友的投票可能有工具刷出来的&#xff0c;觉得应该很有意思&#xff0c;就想自己试一下&#xff0c;玩了半天终于可以操作页面进行投票了&#xff0c;但这个投票做了IP限制&#xff0c;所以工具也无用武之地啊&#xff01;…

Visual Studio “类视图”和“对象浏览器”图标

类视图”和“对象浏览器”显示一些图标&#xff0c;每个图标表示不同类型的符号&#xff0c;如命名空间、类、函数或变量。下表对显示的图标进行说明&#xff0c;并对每个图标进行描述。 图标说明图标说明 命名空间 方法或函数 类 运算符 接口 属性 结构 字段或变量 联…

【数据结构】数据结构知识思维导图

From&#xff1a;https://blog.csdn.net/flowing_wind/article/details/81431354 思维导图源文件&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1Z44pX_jn3P6L4BSS13WmUA 提取码&#xff1a;zmga 数据结构知识思维导图&#xff1a;

特斯拉VS Waymo:谁将赢得无人驾驶汽车竞赛?

来源&#xff1a;腾讯科技据外媒报道&#xff0c;现在正有一场从硅谷延伸到底特律的竞赛正在进行&#xff0c;即谁能最先制造出比人类司机驾车更安全的无人驾驶汽车&#xff1f;与几年前相比&#xff0c;这是一项更为艰巨的任务&#xff0c;因为人类司机了解更多东西&#xff0…

Silverlight Blend动画设计系列十二:三角函数(Trigonometry)动画之自由旋转(Free-form rotation)...

说到对象的旋转&#xff0c;或许就会联想到对象角度的概念。对象的旋转实现实际上就是利用对象的角度改变来实现的位置变换&#xff0c;在《Silverlight & Blend动画设计系列二&#xff1a;旋转动画&#xff08;RotateTransform&#xff09;》一文中有对对象的不同角度变换…

vscode 调试 C++/JavaScript

Microsoft Visual Studio Code&#xff1a;https://blog.csdn.net/freeking101/article/details/86715578 IntelliJ IDEA&#xff1a;https://www.jetbrains.com/products/ 在调试 JavaScript 代码时&#xff0c; 其中 三种 比较 简单&#xff1a; 1.使用 Chrome 等 浏览器 调…

美国三院院士「迈克尔•乔丹」长文论述:为什么说「人工智能革命」尚未发生...

作者&#xff1a;Michael Jordan雷克世界」编译&#xff1a;嗯~是阿童木呀、KABUDA、EVA人工智能&#xff08;AI&#xff09;是当前时代的颂歌。这句话是由技术人员、学者、记者和风险投资家一致提出且真诚赞扬的。就像其他许多从技术学术领域跨越到通用领域的短语一样&#xf…

网络爬虫干货总结!

转载&#xff1a;https://cloud.tencent.com/developer/article/1366434 bilibili 视频 - 聊聊 Python 的应用 - 健壮高效的网络爬虫&#xff1a;https://www.bilibili.com/video/av34379204/ 昨天的时候我参加了掘金组织的一场 Python 网络爬虫主题的分享活动&#xff0c;主要…

GAN 的发展对于研究通用人工智能有什么意义?

作者&#xff1a;Lyken 来源&#xff1a;知乎GAN对于人工智能的意义&#xff0c;可以从它名字的三部分说起&#xff1a;Generative Adversarial Networks。为了方便讲述&#xff0c;也缅怀过去两周在某论坛上水掉的时间&#xff0c;我先从Networks讲起。Networks&#xff1a…

AlldayTest 产品使用--文件

“文件”一栏&#xff0c;可实现新建/打开项目、导入&#xff08;出&#xff09;项目、配置信息等功能。 1、新建项目 运行AlldayTest&#xff0c;点击&#xff1a;“文件”-->“新建”&#xff0c;在出现的窗体内输入新创建项目的名称&#xff0c;选择路径保存即可。Allday…

移动端 爬虫工具 与 方法 介绍

From&#xff1a;https://www.cnblogs.com/zyfd/p/9681080.html 本文主要介绍了移动端爬虫的工具与方法&#xff0c;作为一个入门的大纲。没有详细介绍的也给出了本人学习过程中借鉴的资料的链接&#xff0c;适合对移动端爬虫感兴趣的同学入门。 一、抓包模拟 基本原理&#xf…

“芯痛”之下阿里苦心研发NPU AI芯片究竟哪款PU更厉害?

来源&#xff1a;OFweek人工智能网4月19日&#xff0c;有消息称&#xff0c;阿里巴巴达摩院正在研发一款神经网络芯片——Ali-NPU&#xff0c;主要运用于图像视频分析、机器学习等AI推理计算。按照设计&#xff0c;这款芯片性能将是目前市面上主流CPU、GPU架构AI芯片的10倍&…

(转)Windows 批处理实现 定时打开IE 延时一段时间后 关闭IE

要求实现一个定时器&#xff1a;如题 1、首先建立一个bat文件 内容如下&#xff1a; echo offrem 关闭回显命令 cd C:\Program Files\Internet Explorer\rem 改变当前目录到IE所在目录 start iexplore.exe "http://192.168.0.106:29101/LoadMemoryDB?typeMT&commande…

POE API 驱动 OpenAI API 依赖服务

本文主要是介绍了如何利用 POE 提供的 API 服务来驱动原来依赖 OpenAI 的 API 服务 AIGC 的大模型已经火了很久&#xff0c;但是众所周知的原因 OpenAI 的服务订阅对于大陆用户很不友好。而另一个 AIGC 聚合平台 POE 则对大陆用户比较友好&#xff0c;招行的 VISA 和 Master 卡…