CompletableFuture 详解
目录
简单介绍
常见操作
创建 CompletableFuture
new 关键字
静态工厂方法
处理异步结算的结果
简单介绍
CompletableFuture
同时实现了 Future
和 CompletionStage
接口。
public class CompletableFuture<T> implements Future<T>, CompletionStage<T> {
}
CompletableFuture
除了提供了更为好用和强大的 Future
特性之外,还提供了函数式编程的能力。
Future
接口有 5 个方法:
boolean cancel(boolean mayInterruptIfRunning)
:尝试取消执行任务。boolean isCancelled()
:判断任务是否被取消。boolean isDone()
:判断任务是否已经被执行完成。get()
:等待任务执行完成并获取运算结果。get(long timeout, TimeUnit unit)
:多了一个超时时间。
CompletionStage
接口描述了一个异步计算的阶段。很多计算可以分成多个阶段或步骤,此时可以通过它将所有步骤组合起来,形成异步计算的流水线。
CompletionStage
接口中的方法比较多,CompletableFuture
的函数式能力就是这个接口赋予的。从这个接口的方法参数你就可以发现其大量使用了 Java8 引入的函数式编程。
常见操作
创建 CompletableFuture
常见的创建 CompletableFuture
对象的方法如下:
- 通过 new 关键字。
- 基于
CompletableFuture
自带的静态工厂方法:runAsync()
、supplyAsync()
。
new 关键字
通过 new 关键字创建 CompletableFuture
对象这种使用方式可以看作是将 CompletableFuture
当做 Future
来使用。
下面咱们来看一个简单的案例。
我们通过创建了一个结果值类型为 RpcResponse<Object>
的 CompletableFuture
,你可以把 resultFuture
看作是异步运算结果的载体。
CompletableFuture<RpcResponse<Object>> resultFuture = new CompletableFuture<>();
假设在未来的某个时刻,我们得到了最终的结果。这时,我们可以调用 complete()
方法为其传入结果,这表示 resultFuture
已经被完成了。
// complete() 方法只能调用一次,后续调用将被忽略。
resultFuture.complete(rpcResponse);
你可以通过 isDone()
方法来检查是否已经完成。
public boolean isDone() {return result != null;
}
获取异步计算的结果也非常简单,直接调用 get()
方法即可。调用 get()
方法的线程会阻塞直到 CompletableFuture
完成运算。
rpcResponse = completableFuture.get();
如果你已经知道计算的结果的话,可以使用静态方法 completedFuture()
来创建 CompletableFuture
。
CompletableFuture<String> future = CompletableFuture.completedFuture("hello!");
assertEquals("hello!", future.get());
completedFuture()
方法底层调用的是带参数的 new 方法,只不过,这个方法不对外暴露。
public static <U> CompletableFuture<U> completedFuture(U value) {return new CompletableFuture<U>((value == null) ? NIL : value);
}
静态工厂方法
这两个方法可以帮助我们封装计算逻辑。
static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);
// 使用自定义线程池(推荐)
static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier, Executor executor);
static CompletableFuture<Void> runAsync(Runnable runnable);
// 使用自定义线程池(推荐)
static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor);
runAsync()
方法接受的参数是 Runnable
,这是一个函数式接口,不允许返回值。当你需要异步操作且不关心返回结果的时候可以使用 runAsync()
方法。
@FunctionalInterface
public interface Runnable {public abstract void run();
}
supplyAsync()
方法接受的参数是 Supplier<U>
,这也是一个函数式接口,U
是返回结果值的类型。
@FunctionalInterface
public interface Supplier<T> {/*** Gets a result.** @return a result*/T get();
}
当你需要异步操作且关心返回结果的时候,可以使用 supplyAsync()
方法。
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> System.out.println("hello!"));
future.get();// 输出 "hello!"
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "hello!");
assertEquals("hello!", future2.get());
处理异步结算的结果
当我们获取到异步计算的结果之后,还可以对其进行进一步的处理,比较常用的方法有下面几个:
thenApply()
thenAccept()
thenRun()
whenComplete()
thenApply()
方法接受一个 Function
实例,用它来处理结果。
// 沿用上一个任务的线程池
public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn) {return uniApplyStage(null, fn);
}//使用默认的 ForkJoinPool 线程池(不推荐)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn) {return uniApplyStage(defaultExecutor(), fn);
}
// 使用自定义线程池(推荐)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor) {return uniApplyStage(screenExecutor(executor), fn);
}
如果你不需要从回调函数中获取返回结果,可以使用 thenAccept()
或者 thenRun()
。这两个方法的区别在于 thenRun()
不能访问异步计算的结果。
thenAccept()
方法的参数是 Consumer<? super T>
。
public CompletableFuture<Void> thenAccept(Consumer<? super T> action) {return uniAcceptStage(null, action);
}public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action) {return uniAcceptStage(defaultExecutor(), action);
}public CompletableFuture<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor) {return uniAcceptStage(screenExecutor(executor), action);
}
相关文章:

CompletableFuture 详解
目录 简单介绍 常见操作 创建 CompletableFuture new 关键字 静态工厂方法 处理异步结算的结果 简单介绍 CompletableFuture 同时实现了 Future 和 CompletionStage 接口。 public class CompletableFuture<T> implements Future<T>, CompletionStage<T…...

el-table数据处理
在写表格时遇到,后端返回的数据是对象,并且缺少字段 1.每一条数据加上 一个字段 2.将对象转成数组 以下是数据 {"groupA": {"groupName": null,"orgName": null,"orgId": null,"allPeoper": &quo…...

IPv4网络用户访问IPv6网络服务器
NAT64静态映射为一对一的对应关系,通常应用在IPv4网络主动访问IPv6网络的场景中。 要求位于IPv4网络中的PC通过IPv4地址1.1.1.10能够直接访问位于IPv6网络中Server。 操作步骤 配置FW。 # 配置接口GigabitEthernet 0/0/1的IPv4地址。 <FW> system-view [F…...
程序员是怎么记住代码的?
程序员能记住所有东西吗? 程序员不会记住他们使用的所有代码,相反,他们倾向于阅读文档,学习基本概念,并使用软件社区来解决问题。大约55%的软件开发人员报告每天至少使用一次StackOverflow来帮助解决编程问题。 使用…...
华为云NFS使用API删除大文件目录
最近在使用华为云SFS时,如果一个目录存储文件数超过100W,执行 “rm -rf path”时,存在删不动的情况,可以使用华为云API接口,执行异步删除。 华为官网: 删除文件系统目录_弹性文件服务 SFS_API参考_SFS Tu…...
国家金融监督管理总局明确将数据安全管理纳入操作风险管理范畴
为进一步完善银行保险机构操作风险监管规则,提升银行保险机构的操作风险管理水平,国家金融监督管理总局起草了《银行保险机构操作风险管理办法(征求意见稿)》(以下简称《办法》),现向社会公开征…...
.asScala爆红
转载:asScala报错 解决方案: 导入隐式转换 import scala.collection.JavaConverters._ //asScala需要使用隐式转换 代码中的asScala就可能不标红了,如果标红,就直接去掉,去掉就不报错了...

SOLIDWORKS Utilities应用
在实际的生产设计制造中,经常会遇到同一个零件多个版本,有可能再次调用零件的时间已经是很长时间之后,对于版本之间的区别就不会那么清楚,碰到简单明显的零件还可以轻松的找到区别,但是复杂的零件区别的查找可能会造成…...
发现的宝藏开源软件
1.华夏erp https://github.com/jishenghua/jshERP 2.s2b2c商城 后端 lilishop商城 电商 java商城系统: lilishop商城基于SpringBoot 全端开源 电商商城系统 支持小程序商城 H5商城 APP商城 PC商城 。支持业务模式包含 O2O商城 B2B商城 多语言商城 跨境电商 B2B2C商城 F2B2C商…...

【八】mybatis 日志模块设计
mybatis 日志模块设计 简介:闲来无事阅读一下mybatis的日志模块设计,学习一下优秀开源框架的设计思路,提升自己的编码能力 模块设计 在Mybatis内部定义了4个级别:Error:错误 、warn:警告、debug:调试、trance,日志优…...

Python-如何使用正则表达式
如何利用Python使用正则表达式 目录 正则表达式常用匹配规则 编辑re库的使用 match()方法: search()方法: findall()方法 : sub()方法: compile()方法; 通用匹配 贪婪与非贪婪匹配 贪婪匹配 非贪婪匹配 修饰符 转义匹配 正则表达式是处理字符的强大…...
分解质因子,将一个不小于2的整数分解质因数,例如,输入90,则输出:90=2*3*3*5
假设一个不小于2的整数n,对从2开始的自然数k,这个试探它是否是整数n的一个因子,如果是,则输出该因子,并将n/k的结果赋给n(接下来只需要对n除以已经找到的因子之后的结果继续找因子)。如果n的值不…...

C语言,vs各种报错分析(不断更新)
1.引发了异常: 写入访问权限冲突2.#error: Error in C Standard Library usage 1.引发了异常: 写入访问权限冲突 这里是malloc没有包含头文件<stdlib.h>,包含之后就好了 2.#error: Error in C Standard Library usage 这里就是用C语言写程序时使用了C的头文件…...

AR开发平台 | 探索AR技术在建筑设计中的创新应用与挑战
随着AR技术的不断发展和普及,越来越多的建筑师开始探索AR技术在建筑设计中的应用。AR(增强现实)技术可以通过将虚拟信息叠加到现实场景中,为设计师提供更加直观、真实的建筑可视化效果,同时也可以为用户带来更加沉浸式的体验。 AR开发平台广…...

小白到运维工程师自学之路 第六十集 (docker的概述与安装)
一、概述 1、客户(老板)-产品-开发-测试-运维项目周期不断延后,项目质量差。 随着云计算和DevOps生态圈的蓬勃发展,产生了大量优秀的系统和软件。软件开发人员可以自由选择各种软件应用环境。但同时带来的问题就是需要维护一个非…...

SpringBoot 集成 Elasticsearch
一、版本 spring-boot版本:2.3.7.RELEASEElasticsearch7.8.0版本说明详见 二、Elasticsearch 下载和安装 Elasticsearch 下载 kibana下载 ik分词器下载 配置IK分词器 2.1 解压,在elasticsearch-7.8.0\plugins 路径下新建ik目录 2.2 将ik分词器解压放…...
【ES】使用日志记录
1、修改操作 1、要删除Elasticsearch索引的分区下的数据 <index_name>是要删除数据的索引名称。这个命令会删除该索引下的所有数据。 POST /<index_name>/_delete_by_query {"query": {"match_all": {}} }2、删除特定条件下的数据 要删除a…...

svn还原本地代码
svn代码还原 问题描述:在vscode中修改了代码,没有提交,而且不小心点击了svn更新,导致本地修改的最新代码被覆盖,因为没有提交,所以远程仓库中也没有刚才修改的代码记录 解决: 通过vscode的时间…...

zore-shot,迁移学习和多模态学习
1.zero-shot 定义:在ZSL中,某一类别在训练样本中未出现,但是我们知道这个类别的特征,然后通过语料知识库,便可以将这个类别识别出来。概括来说,就是已知描述,对未知类别(未在训练集中…...

【Golang 接口自动化07】struct转map的三种方式
目录 背景 struct转map 使用json模块 使用reflect模块 使用第三方库 测试 总结 资料获取方法 背景 我们在前面介绍过怎么使用net/http发送json或者map数据,那么它能不能直接发送结构体数据呢?我们今天一起来学习结构体struct转map的三种方法&am…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...

Opencv中的addweighted函数
一.addweighted函数作用 addweighted()是OpenCV库中用于图像处理的函数,主要功能是将两个输入图像(尺寸和类型相同)按照指定的权重进行加权叠加(图像融合),并添加一个标量值&#x…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...

华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...