使用 CompletableFuture 实现异步编程

news/2025/1/12 23:00:00/文章来源:https://www.cnblogs.com/javadd/p/18667571

使用 CompletableFuture 实现异步编程

在现代 Java 开发中,异步编程是一项重要技能。而 CompletableFuture 是从 Java 8 开始提供的一个功能强大的工具,用于简化异步任务的编写和组合。本文将详细介绍 CompletableFuture 的基本使用和一些常见的应用场景。

1. 为什么选择 CompletableFuture?

传统的异步编程通常依赖于回调或 Future,但这些方法存在一些缺陷:

  • 回调地狱:嵌套层级多,代码难以阅读。
  • Future 的 get() 方法是阻塞的,无法真正实现非阻塞式编程。

CompletableFuture 的优势在于:

  1. 支持非阻塞操作。
  2. 提供丰富的 API 用于任务的组合和处理。
  3. 更好的错误处理机制。

2. 基本用法

创建一个 CompletableFuture

import java.util.concurrent.CompletableFuture;public class CompletableFutureExample {public static void main(String[] args) {// 创建一个异步任务CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(1000); // 模拟耗时操作} catch (InterruptedException e) {throw new RuntimeException(e);}return "Hello, CompletableFuture!";});// 非阻塞地获取结果future.thenAccept(result -> System.out.println("Result: " + result));System.out.println("Main thread is not blocked");// 防止主线程退出过早try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}}
}

输出

Main thread is not blocked
Result: Hello, CompletableFuture!

3. 任务组合

thenApply: 转换结果

thenApply 方法用于将异步任务的结果转换为另一种类型。

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> "42").thenApply(Integer::parseInt).thenApply(num -> num * 2);future.thenAccept(result -> System.out.println("Final Result: " + result));

thenCompose: 链式调用

thenCompose 用于在一个任务完成后启动另一个异步任务。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello").thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World!"));future.thenAccept(System.out::println);

thenCombine: 合并两个任务

thenCombine 用于合并两个独立的异步任务的结果。

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");CompletableFuture<String> result = future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2);
result.thenAccept(System.out::println);

4. 异常处理

在异步任务中,异常处理非常重要。CompletableFuture 提供了多种方法来优雅地处理异常。

exceptionally: 捕获异常并返回默认值

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {if (true) {throw new RuntimeException("Something went wrong");}return "Success";
}).exceptionally(ex -> {System.out.println("Exception: " + ex.getMessage());return "Default Value";
});future.thenAccept(System.out::println);

handle: 处理结果和异常

handle 方法无论任务成功还是失败都会执行,并可以访问异常信息。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {if (true) {throw new RuntimeException("Error occurred");}return "Success";
}).handle((result, ex) -> {if (ex != null) {System.out.println("Exception: " + ex.getMessage());return "Recovered from error";}return result;
});future.thenAccept(System.out::println);

5. 实际应用场景

并发请求处理

在需要同时处理多个请求时,可以利用 allOfanyOf 方法。

allOf: 等待所有任务完成

CompletableFuture<Void> allTasks = CompletableFuture.allOf(CompletableFuture.runAsync(() -> System.out.println("Task 1")),CompletableFuture.runAsync(() -> System.out.println("Task 2")),CompletableFuture.runAsync(() -> System.out.println("Task 3"))
);allTasks.thenRun(() -> System.out.println("All tasks completed"));

anyOf: 任意任务完成即返回

CompletableFuture<Object> anyTask = CompletableFuture.anyOf(CompletableFuture.supplyAsync(() -> "Task 1 completed"),CompletableFuture.supplyAsync(() -> "Task 2 completed")
);anyTask.thenAccept(result -> System.out.println("First completed: " + result));

6. 总结

CompletableFuture 是 Java 异步编程的强大工具,提供了丰富的 API 来实现任务的创建、组合和异常处理。通过熟练掌握 CompletableFuture,可以编写更加简洁高效的异步代码。

希望本文能帮助你更好地理解和使用 CompletableFuture

欢迎关注gzh:加瓦点灯
每天推送干货知识

本文由mdnice多平台发布

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

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

相关文章

PCIe总线-存储器域和PCIe总线域访问流程分析(二)

1.概述 PCIe总线的最大特点是像CPU访问DDR一样,可以直接使用地址访问PCIe设备(桥),但不同的是DDR和CPU同属于存储器域,而CPU和PCIe设备属于两个不同的域,PCIe设备(桥)的地址空间属于PCIe总线域。存储器域访问PCIe总线域或者PCIe总线域访问存储器域,需要经过一系列的转…

在Windows上调试iOS Safari中的H5页面

本次开发的web页面需要适配移动端,第一个版本在发布到线上,发现ios设备一直打不开网页,无论是自带的safari浏览器还是其他浏览器,页面经常出现“***页面重复出现错误”,但是在本地以及使用PC浏览器模拟都没有复现该问题。为了进行线上的调试查询了一下如何在windows上调试…

大模型AI应用场景及产品汇总(持续更新)

一、文生图 1. Napkin AINapkin AI 可以基于输入的文本生成各种图示,例如流程图、逻辑关系图等等。https://app.napkin.ai/

大模型AI应用场景汇总(持续更新)

一、文生图 1. Napkin AINapkin AI 可以基于输入的文本生成各种图示,例如流程图、逻辑关系图等等。https://app.napkin.ai/

G1原理—5.G1垃圾回收过程之Mixed GC

大纲 1.Mixed GC混合回收是什么 2.YGC可作为Mixed GC的初始标记阶段 3.Mixed GC并发标记算法详解(一) 4.Mixed GC并发标记算法详解(二) 5.Mixed GC并发标记算法详解(三) 6.并发标记的三色标记法 7.三色标记法如何解决错标漏标问题 8.SATB如何解决错标漏标问题 9.重新梳理Mixed …

AlexNet文献阅读与代码实现

目录AlexNet文献阅读与代码实现文献内容介绍代码实现内容总结 AlexNet文献阅读与代码实现前言:笔者目前研一,刚开始入门深度学习,所以想记录一下自己学习的过程,接下来的时间里,我会定期阅读深度学习领域的经典文献,并尝试用代码实现它们,也欢迎大家积极评论。注:博客本…

c语言的基本类型及输入输出占位符

基本类型 c语言的基本类型:int 【long、short、unsigned、signed(c90)】、char、float、double、_Bool【布尔值】、_complex、_Imaginary【复数和虚数】 输入输出 printf标志字符标志 含义- 转换的结果在字段内左对齐+ 有符号的转换结果总是以+或者-开始空格 如果有符号转换的…

LeetCode:65.有效数字

LeetCode:65.有效数字解题步骤构建一个表示状态的图。遍历字符串,并沿着图走,如果到了某个节点无路可走就返false。遍历结束,如走到3/5/6,就返回true,否则返回false。 extend 2 8 10 16进制 /*** 检查一个字符串是否可以表示为一个有效的数字* @param {string} s - 待检查的…

vs2019项目报错:文件中的类都不能进行设计,解决办法_无法设计基类system.void

文件中的类都不能进行设计,因此未能为该文件显示设计器。设计器检查出文件中有以下类: Form1 --- 无法设计基类“System.Void”。 出现上述错误,解决办法如下: 关闭所有设计窗口(例如form1.cs(设计)),菜单栏生成,清理解决方案,关闭vs2022,重新启动vs2022打开你的项目…

关于VSCode的c/c++环境配置

适用于Windows的VSCode的c/c++环境配置c/c++环境配置写给 初学C/C++的 保姆级 VSCode环境配置第一步 下载VScode 找到官网点下载就好啦下载安装完成之后,启动!点击左侧“拓展”图标下载中文拓展安装好后重启 别关 留着备用 第二步 下载c/c++编译器 这里我使用MinGw实际上 Mi…

G75 拉插 CF622F The Sum of the k-th Powers

视频链接: The Sum of the k-th Powers - 洛谷 | 计算机科学教育新生态// 拉插 O(klogn) #include <iostream> #include <cstring> #include <algorithm> using namespace std;#define LL long long const int N=1e6+10,mod=1e9+7; int n,k; LL ml[N],mr…

Cline 免费插件 + Qwen2.5 大模型,零经验也能开发“对联王”微信小程序

本文详细介绍了如何利用免费的 Cline 插件辅助开发一款名为“对联王”的微信小程序,特别适合希望在春节期间创作春联的用户。文章不仅比较了 Cline 与 Cursor 两款工具的优缺点,还分享了作者实际操作中的经验和建议。通过具体步骤演示,即使是编程新手也能跟随指导,结合微信…