当前位置: 首页 > news >正文

Java8中CompletableFuture.allOf的使用

目录标题

  • CompletableFuture.allOf(...);
  • CompletableFuture.allOf(...).get();
  • CompletableFuture.allOf(...).join();
  • 总结
  • 如何优雅的处理异常呢?

CompletableFuture.allOf(…);

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

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

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");}
}

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

CompletableFuture.allOf(…).get();

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


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");}
}

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

CompletableFuture.allOf(…).join();

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


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");}
}

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

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

allFutures.join();

换成

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

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

总结

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

如何优雅的处理异常呢?

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


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.mrgr.cn/news/62336.html

相关文章:

  • (带源码)宠物主题商场系统 计算机项目 P10083
  • 【MinIO系列】MinIO Client (mc) 完全指南
  • 【python】银行客户流失预测预处理部分,独热编码·标签编码·数据离散化处理·数据筛选·数据分割
  • React第十八节 useEffect 用法使用技巧注意事项详解
  • Vue.js组件开发-使用watch进行深度观察
  • NS3学习——tcpVegas算法代码详解(2)
  • Python飞舞蝙蝠
  • 迪杰斯特拉算法(Dijkstra‘s Algorithm
  • Vue学习记录之二十七 Pinia的使用
  • 97、Python并发编程:多线程实现的两种方式
  • 串口屏控制的自动滑轨
  • 【MySQL】 运维篇—安全管理:数据加密与SSL配置
  • Java基础2-数组
  • Python | Leetcode Python题解之第521题最长特殊序列I
  • C语言 | Leetcode C语言题解之第522题最长特殊序列II
  • C++ | Leetcode C++题解之第522题最长特殊序列II
  • 【多线程场景下事务失效问题如何处理?】
  • 从openjdk17 C++源码角度看 java类成员变量是怎么赋值的
  • 理解环境变量与Shell编程:Linux开发的基础
  • DS18B20+测量系统可编程分辨率高精度数字温度传感器芯片
  • Python——石头剪刀布(附源码+多模式二改优化版)
  • C++学习笔记----9、发现继承的技巧(六)---- 有趣且令人迷惑的继承问题(6)
  • <HarmonyOS第一课>给应用添加通知和提醒的习题
  • VC2012创建弹出式菜单
  • 智能进阶之路:从基础模型到个性化代理—探索Agent与微调的共生之道
  • [专有网络VPC]创建和管理流量镜像