使用CompletableFuture进行异步编程

CompletableFuture是Java 8中引入的一个异步编程工具,它实现了Future和CompletionStage接口,可以用于处理异步任务。CompletableFuture提供了丰富的方法,可以方便地组合多个异步任务,实现复杂的异步逻辑。本文将介绍CompletableFuture的使用。

1. 创建CompletableFuture

要创建一个CompletableFuture,可以使用以下静态方法:

supplyAsync(Supplier<U> supplier): 使用一个供应者函数(Supplier)创建一个异步任务。

runAsync(Runnable runnable): 使用一个Runnable对象创建一个异步任务。

completedFuture(U value): 创建一个已经完成的CompletableFuture。

exceptionally(Function<Throwable, ? extends T> fn): 当异步任务发生异常时,使用一个异常函数处理异常。

 

2. 组合多个异步任务

CompletableFuture提供了很多方法,可以方便地组合多个异步任务。以下是一些常用的组合方法:

thenApply(Function<? super T,? extends U> fn): 对异步任务的结果应用一个函数,并返回一个新的CompletableFuture。

thenAccept(Consumer<? super T> action): 对异步任务的结果执行一个操作,并返回一个新的CompletableFuture。

thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn): 当两个异步任务都完成时,使用一个函数组合它们的结果,并返回一个新的CompletableFuture。

thenCompose(Function<? super T, ? extends CompletionStage<U>> fn): 当异步任务完成时,将其结果应用于另一个异步任务,并返回一个新的CompletableFuture。

allOf(CompletableFuture<?>... cfs): 等待所有给定的CompletableFuture都完成,然后返回一个新的CompletableFuture。

anyOf(CompletableFuture<?>... cfs): 只要给定的任意一个CompletableFuture完成,就返回一个新的CompletableFuture。

 

3. 获取异步任务的结果

可以使用以下方法获取异步任务的结果:

get(): 阻塞当前线程,等待异步任务完成,并返回结果。注意:这个方法会抛出InterruptedException和ExecutionException异常,需注意异常处理。

get(long timeout, TimeUnit unit): 与get()方法一样,区别是增加了等待异步任务完成的超时时间,并且会抛出TimeoutException异常。

join(): 阻塞当前线程,等待异步任务完成,并返回结果。与get()方法类似,但不会抛出异常。

isDone(): 判断异步任务是否已完成。如果已完成,返回true;否则返回false。

isCompletedExceptionally(): 判断异步任务是否因异常而完成。如果因异常而完成,返回true;否则返回false。

exceptionally(Function<Throwable, ? extends T> fn): 当异步任务发生异常时,使用一个异常函数处理异常,并返回一个新的CompletableFuture。

 

4. 示例代码

下面是一个简单的示例,演示了如何使用CompletableFuture组合多个异步任务:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;public class CompletableFutureDemo {private static final Logger LOGGER = LoggerFactory.getLogger(CompletableFutureDemo.class);public static void main(String[] args) throws Exception {CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {sleep(1000);return "Hello";});future1.thenApply(s -> s + " World").thenAccept(message -> LOGGER.info(message));CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {sleep(1000);return "Hello Timeout";});CompletableFuture<Object> future3 = CompletableFuture.supplyAsync(() -> {sleep(50);throw new RuntimeException();}).exceptionally(ex -> {// 处理异常并返回默认值或执行其他操作LOGGER.info("future3" + ex.getMessage());return "默认值";});LOGGER.info("主线程继续执行");try {// 模拟获取结果超时String result2 = future2.get(500, TimeUnit.MILLISECONDS);LOGGER.info(result2);} catch (TimeoutException e) {LOGGER.info("future2超时");}// future3使用了exceptionally(),future3.isCompletedExceptionally()不会为trueString result3 = (String) future3.get();LOGGER.info(result3 + " " + future3.isCompletedExceptionally());CompletableFuture.allOf(future1, future2, future3).join(); // 等待所有任务完成LOGGER.info("主线程结束");}private static void sleep(long millis) {try {TimeUnit.MILLISECONDS.sleep(millis);} catch (InterruptedException e) {throw new IllegalStateException(e);}}
}

程序输出如下:

18:43:50.408 [main] INFO  CompletableFutureDemo - 主线程继续执行
18:43:50.460 [ForkJoinPool.commonPool-worker-3] INFO  CompletableFutureDemo - future3java.lang.RuntimeException
18:43:50.916 [main] INFO  CompletableFutureDemo - future2超时
18:43:50.916 [main] INFO  CompletableFutureDemo - 默认值 false
18:43:51.404 [ForkJoinPool.commonPool-worker-1] INFO  CompletableFutureDemo - Hello World
18:43:51.404 [main] INFO  CompletableFutureDemo - 主线程结束

从上述输出可以看出,多个CompletableFuture与主线程并行执行,并且不会相互影响。这意味着每个CompletableFuture都可以独立地执行其任务,而不需要等待其他任务完成。此外,由于CompletableFuture是异步的,它们不会阻塞主线程的执行,这种并行执行的方式可以提高应用的性能和效率。

 

总结

CompletableFuture是一个强大的异步编程工具,可以方便地组合多个异步任务,实现复杂的异步逻辑。通过使用CompletableFuture,我们可以实现高效的并发编程,并充分利用多核处理器的能力。

 

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

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

相关文章

iOS 设置图标和upload包时显示错误

右键-show in finder-AppIcon.appiconset-然后替换图片 然后遇到个问题 就是图片不能有alpha [Xcode]应用图标&#xff1a;ERROR ITMS-90717: “Invalid App Store Icon. The App Store Icon in the asset catalog in x… 具体操作&#xff1a;只需确保【AppIcon】图片集中不…

test_sizeof

test_sizeof //结论&#xff1a; // sizeof(arrU8)得到的大小是u8类型数组的 **定义大小**&#xff0c;在 初始化的时候用 // strlen(arrU8)得到的大小是u8类型数组的 **实际大小**&#xff0c;在 复制的时候用 //sizeof((char*)arrU8)&#xff0c;把一个u8 * 转成 char *&…

(层次遍历)111. 二叉树的最小深度

原题链接&#xff1a;111. 二叉树的最小深度 思路&#xff1a; 直接层序遍历&#xff0c;遍历一层记录最小深度的遍历depth 最先遇到叶子节点就代表是最小的深度&#xff0c;直接返回depth即可 全代码&#xff1a; class Solution { public:int minDepth(TreeNode* root) {q…

java笔记(一)

一、Java的三大平台 1.Java SE (必学) java语言的标准版&#xff0c;用于桌面开发&#xff0c;是其他两个版本的基础。 桌面应用适合的语言其实是c和C合适&#xff0c;复杂动画等加载时java很慢。 2.Java ME(现在很少用) java语言的小型版本&#xff0c;适用于嵌入式电子设备或…

结合DevOps实践:使用Huawei CodeArts和CCE进行自动化Kubernetes集群部署

文章目录 引言DevOps的价值高效工作流程结束语 引言 在当今企业环境里&#xff0c;DevOps已经成为了实现敏捷、持续集成&#xff08;CI&#xff09;和持续交付&#xff08;CD&#xff09;的关键。这篇博客我们将分享如何使用华为的CodeArts与CCE&#xff08;Cloud Container E…

Leetcode Hot 100之五:15. 三数之和

15.三数之和 题目 给你一个整数数组 nums &#xff0c;判断是否存在三元组 [nums[i], nums[j], nums[k]] 满足 i ! j、i ! k 且 j ! k &#xff0c;同时还满足 nums[i] nums[j] nums[k] 0 。请你返回所有和为 0 且不重复的三元组。 注意&#xff1a;答案中不可以包含重复的…

AlGaN/GaN HFET 五参数模型

标题&#xff1a;A Five-Parameter Model of the AlGaN/GaN HFET 来源&#xff1a;IEEE TRANSACTIONS ON ELECTRON DEVICES&#xff08;15年&#xff09; 摘要—我们引入了AlGaN/GaN异质结场效应晶体管&#xff08;HFET&#xff09;漏极电流Id&#xff08;Vgs&#xff0c;Vds…

Android---屏幕适配的处理技巧

在几年前&#xff0c;屏幕适配一直是困扰 Android 开发工程师的一大问题。但是随着近几年各种屏幕适配方案的诞生&#xff0c;以及谷歌各种适配控件的推出&#xff0c;屏幕适配也显得越来越容易。下面&#xff0c;我们就来总结一下关于屏幕适配的那些技巧。 ConstraintLayout …

万物社用户运营工具:无代码开发下的电商平台和CRM集成

简介&#xff1a;万物社与集简云的引领式连接 万物社&#xff0c;隶属于厦门头号云信息科技有限公司&#xff0c;是一家专注于互联网和相关服务的企业。在日常的业务运营中&#xff0c;万物社通过与集简云的无代码集成&#xff0c;实现了业务流程的自动化和智能化&#xff0c;…

VINS-Mono-后端优化 (二:预积分残差雅可比推导)

文章目录 对位置 δ α \delta\alpha δα 进行求导位置误差 δ α \delta\alpha δα 对平移 P b k w P^{w}_{b_{k}} Pbk​w​ 的求导位置 δ α \delta\alpha δα 对旋转 R w b k R^{b_{k}}_{w} Rwbk​​ 进行求导 对速度 δ β \delta\beta δβ 进行求导速度 δ β…

使用零拷贝技术实现消息转发功能

零拷贝技术介绍&#xff1a;史上最全零拷贝总结-CSDN博客 这是一个简单的基于epoll的Linux TCP代理程序&#xff0c;通过匿名管道和零拷贝技术的splice函数&#xff0c;将两个TCP端口相互连接&#xff0c;并转发数据。 #define _GNU_SOURCE 1 #include <sys/socket.h> …

前端安全方面有哪些攻击方式?

在前端开发中&#xff0c;存在一些常见的安全攻击方式。以下是一些常见的前端安全攻击方式&#xff1a; 1&#xff1a;跨站脚本攻击&#xff08;XSS&#xff09;&#xff1a; XSS攻击是指攻击者通过在网页中注入恶意脚本&#xff0c;使得用户在浏览器中执行该脚本&#xff0c;…

C语言 每日一题 PTA 11.7 day13

1.求e的近似值 自然常数 e 可以用级数 1 1 / 1! 1 / 2! ⋯ 1 / n! ⋯ 来近似计算。 本题要求对给定的非负整数 n&#xff0c;求该级数的前 n 1 项和。 代码实现 #include<stdio.h> void main() {int a, i, j; double b 1; double c 1;printf("请输入一个数\n…

Linux RPM包安装、卸载和升级

我们以安装 apache 程序为例。因为后续章节还会介绍使用源码包的方式安装 apache 程序&#xff0c;读者可以直观地感受到源码包和 RPM 包的区别。 RPM包默认安装路径 通常情况下&#xff0c;RPM 包采用系统默认的安装路径&#xff0c;所有安装文件会按照类别分散安装到表 1 所…

如何使用 GTX750 或 1050 显卡安装 CUDA11+

前言 由于兼容性问题&#xff0c;使得我们若想用较新版本的 PyTorch&#xff0c;通过 GPU 方式训练模型&#xff0c;也得更换较新版本得 CUDA 工具包。然而 CUDA 的版本又与电脑显卡的驱动程序版本关联&#xff0c;如果是低版本的显卡驱动程序安装 CUDA11 及以上肯定会失败。 比…

Java TCP服务端多线程接收RFID网络读卡器上传数据

本示例使用设备介绍&#xff1a;WIFI/TCP/UDP/HTTP协议RFID液显网络读卡器可二次开发语音播报POE-淘宝网 (taobao.com) import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; impor…

计算机毕设 基于机器学习的文本聚类 - 可用于舆情分析

文章目录 0 简介1 项目介绍1.1 提取文本特征1.2 聚类算法选择 2 代码实现2.1 中文文本预处理2.2 特征提取2.2.1 Tf-idf2.2.2 word2vec 2.3 聚类算法2.3.1 k-means 2.3.2 DBSCAN2.4 实现效果2.4.1 tf-idf k-means聚类结果2.4.2 word2vec k-means 聚类结果 最后 0 简介 今天学…

抢量双11!抖音商城「官方立减」 缘何成为“爆单神器”?

10月20日抖音商城双11好物节正式开跑&#xff0c;仅仅三天&#xff0c;抖音商城整体GMV对比去年同期提升了200%&#xff0c;而在开跑一周后&#xff0c;一些品牌的销售额已经超过了今年整个618&#xff0c;可谓增势迅猛。其中&#xff0c;平台官方特别推出的「官方立减」玩法&a…

acwing算法基础之搜索与图论--kruskal算法

目录 1 基础知识2 模板3 工程化 1 基础知识 kruskal算法的关键步骤为&#xff1a; 将所有边按照权重从小到大排序。定义集合S&#xff0c;表示生成树。枚举每条边(a,b,c)&#xff0c;起点a&#xff0c;终点b&#xff0c;边长c。如果结点a和结点b不连通&#xff08;用并查集来…

K8S篇之Pod一直处于Pending状态原因解析

常见现象&#xff1a;Pod一直处于Pending状态。 废话不多说&#xff0c;直接上料。 可能原因1&#xff1a;Pod未被调度到节点上。 当 Pod 一直处于 Pending 状态时&#xff0c;说明该 Pod 还未被调度到某个节点上&#xff0c;需查看 Pod 分析问题原因。 例如执行&#xff1a…