Java8中CompletableFuture.allOf的使用

news/2024/11/3 10:12:48/

目录标题

CompletableFutureallOf_3">CompletableFuture.allOf(…);

CompletableFuture.allOf(…) 本身不会等待所有的 CompletableFuture 完成,它只是返回一个新的 CompletableFuture,这个新未来对象会在所有给定的未来对象完成时完成。

默认情况下,allOf 会等待所有的任务都完成,即使其中有一个失败了,也不会影响其他任务继续执行。

java">public class CompletableFutureExample {public static void main(String[] args) {// 创建一个任务列表List<CompletableFuture<String>> futureList = new ArrayList<>();long startTime = System.currentTimeMillis();// 添加一些异步任务for (int i = 0; i < 5; i++) {final int taskId = i;CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {//睡眠一秒Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}if (taskId == 2) {throw new RuntimeException("task=" + taskId + ",执行异常");}return "Result of Task " + taskId;});futureList.add(future);}long endTime1 = System.currentTimeMillis();System.out.println("[startTime,endTime1]=" + (endTime1 - startTime) + "ms");// 使用 allOf 方法来等待所有任务完成CompletableFuture<Void> allFutures =CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()]));long endTime2 = System.currentTimeMillis();System.out.println("[startTime,endTime2]=" + (endTime2 - startTime) + "ms");long endTime3 = System.currentTimeMillis();System.out.println("[startTime,endTime3]=" + (endTime3 - startTime) + "ms");// 打印每个任务的结果for (CompletableFuture<String> future : futureList) {try {// 注意:如果某个任务失败,这里会抛出异常String result = future.get();System.out.println(result);} catch (Exception e) {System.err.println("Task failed with exception: " + e.getCause());}}long endTime4 = System.currentTimeMillis();System.out.println("[startTime,endTime4]=" + (endTime4 - startTime) + "ms");}
}

执行结果:
在这里插入图片描述

CompletableFutureallOfget_69">CompletableFuture.allOf(…).get();

该代码在调用 get() 时会阻塞当前线程,直到所有的 CompletableFuture 完成。如果其中一个或多个任务失败,它会抛出 ExecutionException,需要捕获并处理异常。

java">
public class CompletableFutureExample {public static void main(String[] args) {// 创建一个任务列表List<CompletableFuture<String>> futureList = new ArrayList<>();long startTime = System.currentTimeMillis();// 添加一些异步任务for (int i = 0; i < 5; i++) {final int taskId = i;CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {//睡眠一秒Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}if (taskId == 2) {throw new RuntimeException("task=" + taskId + ",执行异常");}return "Result of Task " + taskId;});futureList.add(future);}long endTime1 = System.currentTimeMillis();System.out.println("[startTime,endTime1]=" + (endTime1 - startTime) + "ms");// 使用 allOf 方法来等待所有任务完成CompletableFuture<Void> allFutures =CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()]));long endTime2 = System.currentTimeMillis();System.out.println("[startTime,endTime2]=" + (endTime2 - startTime) + "ms");try {allFutures.get();} catch (InterruptedException | ExecutionException e) {System.err.println("An error occurred: " + e.getMessage());}long endTime3 = System.currentTimeMillis();System.out.println("[startTime,endTime3]=" + (endTime3 - startTime) + "ms");// 打印每个任务的结果for (CompletableFuture<String> future : futureList) {try {// 注意:如果某个任务失败,这里会抛出异常String result = future.get();System.out.println(result);} catch (Exception e) {System.err.println("Task failed with exception: " + e.getCause());}}long endTime4 = System.currentTimeMillis();System.out.println("[startTime,endTime4]=" + (endTime4 - startTime) + "ms");}
}

执行结果:
在这里插入图片描述

CompletableFutureallOfjoin_140">CompletableFuture.allOf(…).join();

该代码同样会阻塞当前线程,直到所有的 CompletableFuture 完成。不同于 get(),join() 方法在任务失败时会抛出一个未检查的异常(CompletionException),而不需要处理检查型异常。

java">
public class CompletableFutureExample {public static void main(String[] args) {// 创建一个任务列表List<CompletableFuture<String>> futureList = new ArrayList<>();long startTime = System.currentTimeMillis();// 添加一些异步任务for (int i = 0; i < 5; i++) {final int taskId = i;CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {//睡眠一秒Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}if (taskId == 2) {throw new RuntimeException("task=" + taskId + ",执行异常");}return "Result of Task " + taskId;});futureList.add(future);}long endTime1 = System.currentTimeMillis();System.out.println("[startTime,endTime1]=" + (endTime1 - startTime) + "ms");// 使用 allOf 方法来等待所有任务完成CompletableFuture<Void> allFutures =CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()]));long endTime2 = System.currentTimeMillis();System.out.println("[startTime,endTime2]=" + (endTime2 - startTime) + "ms");allFutures.join();long endTime3 = System.currentTimeMillis();System.out.println("[startTime,endTime3]=" + (endTime3 - startTime) + "ms");// 打印每个任务的结果for (CompletableFuture<String> future : futureList) {try {// 注意:如果某个任务失败,这里会抛出异常String result = future.get();System.out.println(result);} catch (Exception e) {System.err.println("Task failed with exception: " + e.getCause());}}long endTime4 = System.currentTimeMillis();System.out.println("[startTime,endTime4]=" + (endTime4 - startTime) + "ms");}
}

执行结果:
在这里插入图片描述

不用强制捕获异常,但是如果有异常会直接抛出!

java">allFutures.join();

换成

java">try {allFutures.join();
} catch (Exception e) {System.err.println("An error occurred: " + e.getMessage());
}

执行结果:
在这里插入图片描述

总结

仅仅调用 CompletableFuture.allOf(…) 不会导致等待,它只构造一个新的 CompletableFuture。只有调用 get() 或 join() 才会真正等待所有线程执行完毕。get() 需要处理检查型异常,而 join() 则更简洁,不需要处理检查型异常,适合于不需要具体处理的场景。

如何优雅的处理异常呢?

如果异常的情况不需要处理,比如给默认值这种情况,那么下面的写法优雅一些。

java">
public class CompletableFutureExample {public static void main(String[] args) {// 创建一个任务列表List<CompletableFuture<String>> futureList = new ArrayList<>();long startTime = System.currentTimeMillis();// 添加一些异步任务for (int i = 0; i < 5; i++) {final int taskId = i;CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {//睡眠一秒Thread.sleep(2000);} catch (InterruptedException e) {throw new RuntimeException(e);}if (taskId == 2) {throw new RuntimeException("task=" + taskId + ",执行异常");}return "Result of Task " + taskId;}).handle((result, ex) -> {if (ex != null) {// 处理异常并返回 nullSystem.err.println("Task failed: " + ex.getCause());return null;  // 返回 null 表示任务失败}return result;  // 返回结果});futureList.add(future);}long endTime1 = System.currentTimeMillis();System.out.println("[startTime,endTime1]=" + (endTime1 - startTime) + "ms");// 使用 allOf 方法来等待所有任务完成CompletableFuture<Void> allFutures =CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()]));// 处理结果和异常CompletableFuture<List<String>> resultsFuture = allFutures.thenApply(v ->futureList.stream().map(CompletableFuture::join)  // 使用 join() 获取结果.filter(result -> result != null)  // 过滤掉失败的结果.collect(Collectors.toList())  // 收集成功的结果);long endTime2 = System.currentTimeMillis();System.out.println("[startTime,endTime2]=" + (endTime2 - startTime) + "ms");// 打印每个任务的结果List<String> futureResultList = resultsFuture.join();long endTime3 = System.currentTimeMillis();System.out.println("[startTime,endTime3]=" + (endTime3 - startTime) + "ms");for (String result : futureResultList) {System.out.println(result);}long endTime4 = System.currentTimeMillis();System.out.println("[startTime,endTime4]=" + (endTime4 - startTime) + "ms");}
}

输出结果:

在这里插入图片描述

在这里插入图片描述


http://www.ppmy.cn/news/1543317.html

相关文章

【Kubernets】k8s进阶-深入了解一下Label的用法

文章目录 标签的用法标签选择器的用法查询方式 &#x1f914; 标签选择器有哪些高级用法&#xff1f;在Kubernetes中&#xff0c;标签选择器的高级用法非常灵活&#xff0c;允许进行复杂的资源选择和操作。以下是一些高级用法的例子&#xff1a;除了标签Label&#xff0c; 还有…

VBA在低版本Excel中创建unique函数的方法

UNIQUE函数通常用来返回列表或范围中的一系列唯一值&#xff0c;也就是过滤掉重复值。我们可以利用 UNIQUE 函数 与 FILTER 函数的组合进行深度筛选&#xff0c;但在Excel2021以上版本才会提供该函数&#xff0c;在低版本的Excel中我们可以使用VBA创建一个自定义函数来模仿高版…

HTML、JavaScript和CSS实现注册页面设计

目录 一、实现要求 二、实现页面图 1、注册页面 2.用户ID、用户名、口令验证成功后显示页面 三、用户ID、用户名、口令、确定口令验证逻辑js代码 1、验证用户ID 2、验证用户名 3、验证口令密码 四、总结 五、代码仓库 一、实现要求 综合使用HTML、JavaScript和CSS进…

uni-app使用movable-area 实现数据的拖拽排序功能

文档地址 template部分 <movable-area :style"getAreaStyle"><movable-view class"table-row" v-for"v,i in move.list":key"v.id":y"v.y"change"handle_moving"direction"vertical"touchst…

Linux 系统性能调优技巧

Linux 是一个强大且灵活的操作系统&#xff0c;广泛应用于服务器、云计算、嵌入式系统以及桌面环境。在高负载和复杂应用环境中&#xff0c;Linux 系统性能调优变得尤为重要。本文将深入介绍 Linux 系统性能调优的基本概念和实践技巧&#xff0c;涵盖 CPU、内存、磁盘 I/O、网络…

BERT,RoBERTa,Ernie的理解

BERT&#xff1a; 全称&#xff1a;Bidirectional Encoder Representations from Transformers。可以理解为 “基于 Transformer 的双向编码器表示”。含义&#xff1a;是一种用于语言表征的预训练模型。它改变了以往传统单向语言模型预训练的方式&#xff0c;能够联合左侧和右…

C/C++中的内存对齐详解

一、内存对齐概述 &#xff08;一&#xff09;内存对齐的定义与重要性 内存对齐在 C/C 中是一种重要的机制&#xff0c;它确保数据在内存中的存储地址满足特定的规则。具体来说&#xff0c;计算机系统对不同的数据类型有合法地址的限制&#xff0c;要求对象的地址必须是特定值…

C++学习:类和对象(二)

一、默认成员函数 1. 什么是默认成员函数&#xff1f; 在C中&#xff0c;每个类都有一些特殊的成员函数&#xff0c;如果程序员没有显式地声明&#xff0c;编译器会自动为类生成这些函数&#xff0c;这些函数称为默认成员函数 2. 默认成员函数列表 默认构造函数&#xff08…