java之使用CompletableFuture入门2

news/2024/12/27 21:36:39/文章来源:https://www.cnblogs.com/luo630/p/18448304

Java 17

-

 

序章

本文介绍用过的 allOf、anyOf 函数的用法。

 

allOf 函数原型

两点:

1、没有返回值。

2、参数 cfs 中 任何一个 都不能是 null。

 

anyOf 函数原型

两点:

1、有返回值,为 Object。

2、参数 cfs 中 任何一个 都不能是 null。

 

allOf

测试意图:

多个任务正常执行。ben发布于博客园

任务中任何一个发生异常。

 

测试代码:

// 调用:
// testAllOf(false);
// testAllOf(true);
// /*** 测试 allOf 函数* @param makeEx 制造异常*/private static void testAllOf(boolean makeEx) {printWithTime("allOf 0: makeEx=" + makeEx);CompletableFuture<String>[] arr = new CompletableFuture[4];IntStream.range(1,4).forEach(i->{arr[i-1] = CompletableFuture.supplyAsync(()->{var tn = Thread.currentThread().getName();printWithTime("start: " + tn + ", i=" + i);try {// 2 4 6TimeUnit.SECONDS.sleep(i * 2);} catch (InterruptedException e) {throw new RuntimeException(e);}printWithTime("end: " + tn + ", i=" + i);return "t#" + i;});});int len = 3;// 调试:发生异常// 开关1:第4个是否发生异常
//        arr[3] = CompletableFuture.supplyAsync(()->{
//            var tn = Thread.currentThread().getName();
//            printWithTime("start: " + tn + ", i=OUT");
//
//            if (makeEx) {
//                throw new RuntimeException("发生了异常...boom");
//            }
//
//            try {
//                TimeUnit.SECONDS.sleep(5);
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
//            printWithTime("end: " + tn + ", i=OUT");
//            return "t#OUT";
//        });
//        len = 4;printWithTime("allOf 1");CompletableFuture<Void> allTasks = CompletableFuture.allOf(Arrays.copyOf(arr, len));printWithTime("allOf 2");try {allTasks.get();printWithTime("allOf 3");} catch (InterruptedException e) {printWithTime("e 1");throw new RuntimeException(e);} catch (ExecutionException e) {printWithTime("e 2");// 开关2:throw new RuntimeException(e);}printWithTime("allOf 4");for (CompletableFuture<String> cfs : arr) {if (Objects.nonNull(cfs)) {try {printWithTime("result="+ cfs.get());} catch (InterruptedException e) {printWithTime("e 3");throw new RuntimeException(e);} catch (ExecutionException e) {printWithTime("e 4");throw new RuntimeException(e);}} else {printWithTime("cfs is null");}}printWithTime("allOf end.");}

 

所有线程正常执行

调用 testAllOf(false) 的结果

三个线程在执行,都顺利执行了,分别等待了2、4、6秒。ben发布于博客园

所有执行完毕后,一起输出了结果。

[2024-10-06 20:45:41] allOf 0: makeEx=false
[2024-10-06 20:45:41] allOf 1
[2024-10-06 20:45:41] allOf 2
[2024-10-06 20:45:41] start: ForkJoinPool.commonPool-worker-3, i=3
[2024-10-06 20:45:41] start: ForkJoinPool.commonPool-worker-2, i=2
[2024-10-06 20:45:41] start: ForkJoinPool.commonPool-worker-1, i=1
[2024-10-06 20:45:43] end: ForkJoinPool.commonPool-worker-1, i=1
[2024-10-06 20:45:45] end: ForkJoinPool.commonPool-worker-2, i=2
[2024-10-06 20:45:47] end: ForkJoinPool.commonPool-worker-3, i=3
[2024-10-06 20:45:47] allOf 3
[2024-10-06 20:45:47] allOf 4
[2024-10-06 20:45:47] result=t#1
[2024-10-06 20:45:47] result=t#2
[2024-10-06 20:45:47] result=t#3
[2024-10-06 20:45:47] cfs is null
[2024-10-06 20:45:47] allOf end.

 

线程执行发生异常

操作:打开 开关1,给数组添加第4给任务。ben发布于博客园

执行结果:

前3个正常执行了,第4个发生异常。

allOf 会等到 所有线程 都有结果——正常的 或 异常的。

allOf 中 任何一个发生异常时,allOf 发生异常

[2024-10-06 20:53:29] allOf 0: makeEx=true
[2024-10-06 20:53:29] allOf 1
[2024-10-06 20:53:29] allOf 2
[2024-10-06 20:53:29] start: ForkJoinPool.commonPool-worker-4, i=OUT
[2024-10-06 20:53:29] start: ForkJoinPool.commonPool-worker-2, i=2
[2024-10-06 20:53:29] start: ForkJoinPool.commonPool-worker-1, i=1
[2024-10-06 20:53:29] start: ForkJoinPool.commonPool-worker-3, i=3
[2024-10-06 20:53:31] end: ForkJoinPool.commonPool-worker-1, i=1
[2024-10-06 20:53:33] end: ForkJoinPool.commonPool-worker-2, i=2
[2024-10-06 20:53:35] end: ForkJoinPool.commonPool-worker-3, i=3
[2024-10-06 20:53:35] e 2
Exception in thread "main" java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.RuntimeException: 发生了异常...boom

 

上面在 e 2 发生异常,但是,throw 了异常,如果不抛出异常呢?

操作:关闭 开关2——注释掉 抛出异常

执行结果:

e 2 后可以继续执行。

执行到 第4个发生异常的线程时,抛出异常。ben发布于博客园

[2024-10-06 20:58:01] allOf 0: makeEx=true
[2024-10-06 20:58:01] allOf 1
[2024-10-06 20:58:01] allOf 2
[2024-10-06 20:58:01] start: ForkJoinPool.commonPool-worker-4, i=OUT
[2024-10-06 20:58:01] start: ForkJoinPool.commonPool-worker-2, i=2
[2024-10-06 20:58:01] start: ForkJoinPool.commonPool-worker-1, i=1
[2024-10-06 20:58:01] start: ForkJoinPool.commonPool-worker-3, i=3
[2024-10-06 20:58:03] end: ForkJoinPool.commonPool-worker-1, i=1
[2024-10-06 20:58:05] end: ForkJoinPool.commonPool-worker-2, i=2
[2024-10-06 20:58:07] end: ForkJoinPool.commonPool-worker-3, i=3
[2024-10-06 20:58:07] e 2
[2024-10-06 20:58:07] allOf 4
[2024-10-06 20:58:07] result=t#1
[2024-10-06 20:58:07] result=t#2
[2024-10-06 20:58:07] result=t#3
[2024-10-06 20:58:07] e 4
Exception in thread "main" java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.RuntimeException: 发生了异常...boom

 

处理异常的方式

当然,可以用 exceptionally(...) 函数来处理 异常,避免异常传到外面的处理流程中。

 

anyOf

任何一个 任务执行完,立即返回其结果——正常的、异常的。ben发布于博客园

注意,是 有返回值 的。

 

正常执行1

将 上面测试代码的 allOf 替换为 anyOf 进行测试。代码:

    /*** 测试 anyOf 函数* @param makeEx 制造异常*/private static void testAnyOf(boolean makeEx) {printWithTime("anyOf 0: makeEx=" + makeEx);CompletableFuture<String>[] arr = new CompletableFuture[4];IntStream.range(1,4).forEach(i->{arr[i-1] = CompletableFuture.supplyAsync(()->{var tn = Thread.currentThread().getName();printWithTime("start: " + tn + ", i=" + i);try {// 2 4 6TimeUnit.SECONDS.sleep(i * 2);} catch (InterruptedException e) {throw new RuntimeException(e);}printWithTime("end: " + tn + ", i=" + i);return "t#" + i;});});int len = 3;// 调试:发生异常// 开关1:第4个是否发生异常
//        arr[3] = CompletableFuture.supplyAsync(()->{
//            var tn = Thread.currentThread().getName();
//            printWithTime("start: " + tn + ", i=OUT");
//
//            if (makeEx) {
//                throw new RuntimeException("发生了异常...boom");
//            }
//
//            try {
//                TimeUnit.SECONDS.sleep(5);
//            } catch (InterruptedException e) {
//                throw new RuntimeException(e);
//            }
//            printWithTime("end: " + tn + ", i=OUT");
//            return "t#OUT";
//        });
//        len = 4;printWithTime("anyOf 1");CompletableFuture<Object> allTasks = CompletableFuture.anyOf(Arrays.copyOf(arr, len));printWithTime("anyOf 2");try {Object x = allTasks.get();printWithTime("anyOf 3: x=" + x);} catch (InterruptedException e) {printWithTime("e 1");throw new RuntimeException(e);} catch (ExecutionException e) {printWithTime("e 2");// 开关2:throw new RuntimeException(e);}printWithTime("anyOf 4");for (CompletableFuture<String> cfs : arr) {if (Objects.nonNull(cfs)) {try {printWithTime("result="+ cfs.get());} catch (InterruptedException e) {printWithTime("e 3");throw new RuntimeException(e);} catch (ExecutionException e) {printWithTime("e 4");throw new RuntimeException(e);}} else {printWithTime("cfs is null");}}printWithTime("anyOf end.");}

testAnyOf(false) 执行结果:ben发布于博客园

3个任务,休眠2 秒的先返回,anyOf get到结果了。

但是,其它2个任务 还是会继续执行完,在后面的代码 get时,出现等待的情况。

当然,因为 各个任务的 休眠时间不同,总是 休眠最短的 返回。

[2024-10-06 21:10:37] anyOf 0: makeEx=false
[2024-10-06 21:10:37] anyOf 1
[2024-10-06 21:10:37] anyOf 2
[2024-10-06 21:10:37] start: ForkJoinPool.commonPool-worker-2, i=2
[2024-10-06 21:10:37] start: ForkJoinPool.commonPool-worker-3, i=3
[2024-10-06 21:10:37] start: ForkJoinPool.commonPool-worker-1, i=1
[2024-10-06 21:10:39] end: ForkJoinPool.commonPool-worker-1, i=1
[2024-10-06 21:10:39] anyOf 3: x=t#1
[2024-10-06 21:10:39] anyOf 4
[2024-10-06 21:10:39] result=t#1
[2024-10-06 21:10:41] end: ForkJoinPool.commonPool-worker-2, i=2
[2024-10-06 21:10:41] result=t#2
[2024-10-06 21:10:43] end: ForkJoinPool.commonPool-worker-3, i=3
[2024-10-06 21:10:43] result=t#3
[2024-10-06 21:10:43] cfs is null
[2024-10-06 21:10:43] anyOf end.
[2024-10-06 21:10:43] end main.

Process finished with exit code 0

 

正常执行:随机结果

3个任务,全部休眠 4秒。ben发布于博客园

TimeUnit.SECONDS.sleep(4);

执行结果:

anyOf 3: x=t#1、2、3 都有可能,随机的。

 

线程执行发生异常

在上一步的基础上,打开开关1——取消注释。

休眠4秒后,抛出异常(和之前不同):

// 调试:发生异常
// 开关1:第4个是否发生异常
arr[3] = CompletableFuture.supplyAsync(()->{var tn = Thread.currentThread().getName();printWithTime("start: " + tn + ", i=OUT");try {TimeUnit.SECONDS.sleep(4);} catch (InterruptedException e) {throw new RuntimeException(e);}if (makeEx) {throw new RuntimeException("发生了异常...boom");}printWithTime("end: " + tn + ", i=OUT");return "t#OUT";
});
len = 4;
testAnyOf(true) 执行结果:

有时候结果是正常的,可以走到 e 4;有时候结果是异常的,走到 e 2 就结束了。

符合预期。ben发布于博客园

 

同 allOf 函数,可以用 exceptionally 函数来处理——异常时内部处理,不干扰外面流程。

 

小结

一个场景:

在获取数据库数据时,可以同时获取多个,再在程序中进行计算。

 

---end---ben发布于博客园

 

本文链接:

https://www.cnblogs.com/luo630/p/18448304

 

参考资料

1、4.异步编程利器:CompletableFuture详解-Java开发实战
2021-06-06
作者:捡田螺的小男孩
https://juejin.cn/post/6970558076642394142

2、CompletableFuture 组合处理 allOf 和 anyOf太赞了!
2021-05-31
作者:码农架构
https://juejin.cn/post/6968286631614742535

3、

 

ben发布于博客园

ben发布于博客园

 

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

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

相关文章

VMware Aria Operations for Logs 8.18 发布,新增功能概览

VMware Aria Operations for Logs 8.18 发布,新增功能概览VMware Aria Operations for Logs 8.18 - 集中式日志管理 请访问原文链接:https://sysin.org/blog/vmware-aria-operations-for-logs/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org集中式日志管理 V…

VMware Aria Operations for Networks 6.13 发布,新增功能概览

VMware Aria Operations for Networks 6.13 发布,新增功能概览VMware Aria Operations for Networks 6.13 - 网络和应用监控工具 请访问原文链接:https://sysin.org/blog/vmware-aria-operations-for-networks/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org…

读数据工程之道:设计和构建健壮的数据系统01数据工程概述

数据工程概述1. 数据工程 1.1. 自从公司开始使用数据做事,数据工程就以某种形式存在了1.1.1. 预测性分析、描述性分析和报告1.2. 数据工程师获取数据、存储数据,并准备数据供数据科学家、分析师和其他人使用 1.3. 数据工程是系统和流程的开发、实施和维护,这些系统和流程接收…

安装socks5的一次尝试

1. 下载并自动配置socks5sudo wget https://ap-guangzhou-1257892306.cos.ap-guangzhou.myqcloud.com/asi/httpsocks5.sh && sh httpsocks5.sh 执行下载脚本 wget —no-check-certificate https://raw.github.com/Lozy/danted/master/install.sh -O install.sh执行安装…

形函数的构造7

形函数构造 构造单元1的一般近似函数 \(\overline{V(x)}^{(1)}\),由于该单元只有两个节点\(x_1\)和\(x_2\),我们选择包含两个参数\(\alpha_1\)和\(\alpha_2\)的近似方程 \[\overline{V(x)}^{(1)}=\alpha_1+\alpha_2\times x \]令试函数与\(V(x)\)在节点\(x_1\)和\(x_2\)处相等…

等参单元4

在自然坐标系中 , \(\xi_2=1\)和 \(\xi_2=1\),在物理坐标系中为 \(x_1\) 和\(x_2\),相应的节点位移为\(u_1\) 和\(u_2\) 。 在自然坐标系 下,单元形函数为 \[N_{1}(\xi)=\frac{1}{2}(1-\xi)\\N_{2}(\xi)=\frac{1}{2}(1+\xi) \] 利用形函数,在自然坐标系下单元内的任一点 \(…

二维或三维的分布积分方法(格林公式)7

二维或三维的分布积分(格林公式) 分布积分对下式积分 \[\int\int_{\Omega}\Phi\frac{\partial\Psi}{\partial x}\mathrm{d}x\mathrm{d}y \] 首先对变量\(x\)分布积分 \[\int\limits_{X_L}^{X_R}U\mathrm{d}V=(UV_{X=X_R}-UV_{X=X_L})-\int\limits_{X_L}^{X_R}V\mathrm{d}U \]…

流体力学8-3

第一章 1.1 流体的概念 任何固体材料都有一个强度极限,即使合外力和力矩都为零,它的内部也可能会存在着拉力、压力或者剪切力。当这些内应力超过了材料的强度极限时,固体就会被破坏,从而产生运动。微观上体现为断裂处的分子(或原子)之间的化学键被破坏,失去了相互的作用…

应力分析7

目录3.1 几个基本概念3.3 任意斜截面上的应力3.4 主应力及应力(张量)不变量3.5 最大、最小正应力和最大剪应力 3.1 几个基本概念 • 外力 外力指的是我们熟知的机械力、电磁力等,物体因外力作用而变形。作用于物体的外力可分为体积力和表面 力,它们分别简称为体力和面力。…

塑性力学本构模型基本框架7

目录一. 引言二. 塑性应变增量推导三. 弹塑性刚度矩阵推导四. 塑性模量理解五. 小结 一. 引言 弹塑性理论定义材料在荷载作用下的变形是弹性变形和塑性变形之和,其中研究塑性变形需要解决三个方面的问题: ①产生塑性变形的起点; ②产生塑性变形的方向; ③产生塑性变形的大小…

屈服条件8

屈服条件 2.1 应力偏张量及性质 在空间应力状态下,适当选择坐标轴,可让剪应力为零,而只剩正应力,这样相互垂直的坐标轴的方向叫应力张量的主方向,或者主轴。 与主方向垂直的面叫主平面,该面上的正应力叫主应力,三个主应力分别用 $\sigma_1,\sigma_2,\sigma_3 \(表示,则…