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

future和CompletableFuture

future

什么是future

Future 类是并发编程中一个非常重要的工具。它主要用于表示一个异步计算的结果,允许你在计算完成后获取结果或处理异常。Java 的 Future 也常常与线程池(如 ExecutorService)结合使用,用来执行并行任务,并返回任务的执行结果。

Java 中的 Future 主要用于以下几个场景:

异步计算:当我们希望在不阻塞主线程的情况下执行任务,并能在稍后获取任务的结果时,可以使用 Future。
任务控制:通过 Future,我们可以检查任务是否完成,获取任务的执行结果,或者取消正在执行的任务。
避免阻塞:Future 允许我们在等待计算结果时,不会阻塞主线程。

future常见方法

在 Java 中,Future 类提供了几种常见的方法来管理异步任务的执行:

get():等待异步任务完成并获取结果,如果任务抛出异常,会重新抛出该异常。
get(long timeout, TimeUnit unit):带有超时限制的 get 方法,等待任务完成的最长时间,超时后抛出 TimeoutException。
cancel(boolean mayInterruptIfRunning):取消任务。如果任务已经开始执行,且 mayInterruptIfRunning 为 true,会中断任务。
isDone():检查任务是否已经完成。
isCancelled():检查任务是否已经被取消。

使用示例

get()简单的异步任务

使用 ExecutorService 提交任务,并通过 Future 获取任务的结果

import java.util.concurrent.*;public class FutureExample {public static void main(String[] args) throws InterruptedException, ExecutionException {ExecutorService executorService = Executors.newFixedThreadPool(1);// 提交一个异步任务Future<Integer> future = executorService.submit(() -> {// 模拟一些计算Thread.sleep(2000);return 42;  // 返回结果});// 在任务完成之前执行其他操作System.out.println("Main thread is doing other work...");// 获取任务的结果,若任务未完成,则会阻塞直到任务完成Integer result = future.get();  // 阻塞直到任务完成System.out.println("Task result: " + result);executorService.shutdown();}
}
带超时的 get() 方法

Future 的 get(long timeout, TimeUnit unit) 方法允许我们为任务设置一个超时。如果在指定的时间内任务没有完成,会抛出 TimeoutException。

import java.util.concurrent.*;public class FutureTimeoutExample {public static void main(String[] args) {ExecutorService executorService = Executors.newFixedThreadPool(1);// 提交一个任务Future<Integer> future = executorService.submit(() -> {Thread.sleep(5000);  // 模拟长时间任务return 100;});try {// 设置超时,等待最多 3 秒Integer result = future.get(3, TimeUnit.SECONDS);System.out.println("Task result: " + result);} catch (TimeoutException e) {System.out.println("Task timed out!");future.cancel(true);  // 取消任务} catch (InterruptedException | ExecutionException e) {System.out.println("An error occurred: " + e.getMessage());}executorService.shutdown();}
}
取消任务cancel(boolean mayInterruptIfRunning)

通过 future.cancel(true) 来取消任务。true 表示如果任务已经开始执行,允许中断任务。

import java.util.concurrent.*;public class FutureCancelExample {public static void main(String[] args) throws InterruptedException {ExecutorService executorService = Executors.newFixedThreadPool(1);// 提交一个长时间运行的任务Future<Integer> future = executorService.submit(() -> {Thread.sleep(5000);return 100;});// 让主线程等待 2 秒钟Thread.sleep(2000);// 取消任务boolean isCancelled = future.cancel(true);if (isCancelled) {System.out.println("Task was successfully cancelled.");} else {System.out.println("Task could not be cancelled.");}executorService.shutdown();}
}
批量任务处理与 isDone() 方法

在实际开发中,有时我们需要提交多个任务,并等待它们完成。可以使用 isDone() 来检查每个任务是否已完成。

import java.util.concurrent.*;public class FutureBatchExample {public static void main(String[] args) throws InterruptedException {ExecutorService executorService = Executors.newFixedThreadPool(3);// 提交多个任务Future<Integer> future1 = executorService.submit(() -> {Thread.sleep(1000);return 10;});Future<Integer> future2 = executorService.submit(() -> {Thread.sleep(2000);return 20;});Future<Integer> future3 = executorService.submit(() -> {Thread.sleep(3000);return 30;});// 检查任务是否完成while (!future1.isDone() || !future2.isDone() || !future3.isDone()) {System.out.println("Waiting for tasks to complete...");Thread.sleep(500);}System.out.println("Task 1 result: " + future1.get());System.out.println("Task 2 result: " + future2.get());System.out.println("Task 3 result: " + future3.get());executorService.shutdown();}
}

CompletableFuture

什么是CompletableFuture

CompletableFuture 是 Java 8 引入的一个类,位于 java.util.concurrent 包中。它是 Future 类的一个增强版本,用于处理异步编程。与 Future 类不同,CompletableFuture 不仅支持基本的异步任务执行和结果获取,还提供了更多的功能,允许任务的组合、回调的注册、异常处理以及支持非阻塞地执行多个任务。

CompletableFuture和future的区别

特性FutureCompletableFuture
异步计算结果的获取通过 get() 方法,获取结果时会阻塞当前线程。支持非阻塞的异步计算,使用 thenApply() 等方法继续处理结果。
任务组合不支持任务的组合,无法在多个任务完成后做进一步操作。支持任务的组合,提供 thenApply(), thenCombine(), allOf() 等方法来组合多个异步任务。
异常处理如果任务执行出现异常,可以通过 get() 抛出异常,但没有方便的回调处理机制。支持更丰富的异常处理,通过 handle(), exceptionally() 等方法处理异常。
任务手动完成不支持手动完成任务。可以手动完成任务,使用 complete() 或 completeExceptionally() 来控制任务的完成。
响应式编程仅支持简单的异步结果获取。支持响应式编程,能够注册多个回调处理器来响应任务的状态变化

CompletableFuture的常用方法

supplyAsync():异步执行一个返回结果的任务。
runAsync():异步执行一个没有返回结果的任务。
thenApply():任务完成后,基于结果执行一个转换操作。
thenAccept():任务完成后,基于结果执行一个操作,但不返回结果。
thenCombine():当两个任务都完成时,结合两个任务的结果。
exceptionally():处理异步任务的异常。
allOf():等待多个任务同时完成。
anyOf():等待多个任务中任意一个完成。

CompletableFuture使用案例

基本的异步计算

使用 supplyAsync() 提交了一个异步任务,主线程通过 get() 等待异步任务的完成并获取结果。

import java.util.concurrent.*;public class CompletableFutureExample {public static void main(String[] args) throws InterruptedException, ExecutionException {// 使用 supplyAsync 异步执行任务CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {// 模拟一个长时间的计算try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); }return 42;  // 返回结果});// 获取计算结果(会阻塞直到结果完成)Integer result = future.get();System.out.println("Task result: " + result);}
}

任务的组合

通过 thenApply() 和 thenCombine() 等方法,我们可以将多个异步任务组合在一起,完成更复杂的计算。

import java.util.concurrent.*;public class CompletableFutureCombinationExample {public static void main(String[] args) throws InterruptedException, ExecutionException {CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);// thenCombine() 用于将两个异步任务的结果合并CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (x, y) -> x + y);// 获取合并结果Integer result = combinedFuture.get();System.out.println("Combined result: " + result);  // 输出 30}
}
异常处理

CompletableFuture 提供了更好的异常处理机制,可以通过 exceptionally() 来处理任务中的异常。

import java.util.concurrent.*;public class CompletableFutureExceptionExample {public static void main(String[] args) throws InterruptedException, ExecutionException {CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {if (true) {throw new RuntimeException("Something went wrong!");}return 42;});// 使用 exceptionally() 处理异常CompletableFuture<Integer> handledFuture = future.exceptionally(ex -> {System.out.println("Handling exception: " + ex.getMessage());return 0;  // 异常处理后返回默认值});Integer result = handledFuture.get();System.out.println("Task result: " + result);  // 输出 "Task result: 0"}
}
等待多个任务

通过 allOf() 方法,我们可以等待多个异步任务全部完成,然后处理它们的结果。

import java.util.concurrent.*;public class CompletableFutureAllOfExample {public static void main(String[] args) throws InterruptedException, ExecutionException {CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);CompletableFuture<Integer> future3 = CompletableFuture.supplyAsync(() -> 30);// 等待所有任务完成CompletableFuture<Void> allOf = CompletableFuture.allOf(future1, future2, future3);// 等待所有任务完成后获取结果allOf.get();  // 阻塞,直到所有任务完成// 获取每个任务的结果System.out.println("Result of future1: " + future1.get());System.out.println("Result of future2: " + future2.get());System.out.println("Result of future3: " + future3.get());}
}
响应式编程

CompletableFuture 支持更为灵活的异步执行流,可以在任务完成后注册回调处理。

import java.util.concurrent.*;public class CompletableFutureCallbackExample {public static void main(String[] args) {CompletableFuture.supplyAsync(() -> {return 42;}).thenApply(result -> {System.out.println("Task result: " + result);return result * 2;  // 处理任务结果}).thenAccept(finalResult -> {System.out.println("Final result: " + finalResult);  // 输出最终结果});}
}

那么是否是CompletableFuture能完全替代Future

可以的,可以理解为CompletableFuture是Future的增强版本,就像Springboot能完全替代SpringMVC一样

CompletableFuture 完全可以替代 Future,因为它提供了 Future 的所有功能,并增加了更多强大的特性,如任务组合、异常处理、回调等。

对于复杂的异步操作和任务链式调用,CompletableFuture 是更好的选择,它使得异步编程更加灵活和简洁。

对于简单的任务执行和结果获取,如果没有任务组合、回调和异常处理的需求,Future 仍然是一个简单有效的选择。

总结来说,CompletableFuture 是更现代和强大的异步工具,Future 仍然可以在某些简单场景下使用,但大多数情况可以考虑使用 CompletableFuture 来简化代码并提高效率。

Future用来接收excutorservice执行的线程池,而Completable底层也是执行的线程池,使用默认线程池 ForkJoinPool.commonPool(),且可以更改为自定义的线程池,所以和Futre并没什么实质上的区别,只是一个增强版

相关文章:

future和CompletableFuture

future 什么是future Future 类是并发编程中一个非常重要的工具。它主要用于表示一个异步计算的结果&#xff0c;允许你在计算完成后获取结果或处理异常。Java 的 Future 也常常与线程池&#xff08;如 ExecutorService&#xff09;结合使用&#xff0c;用来执行并行任务&…...

如何通过深度学习提升大分辨率图像预测准确率?

随着科技的不断进步&#xff0c;图像处理在各个领域的应用日益广泛&#xff0c;特别是在医疗影像、卫星遥感、自动驾驶、安防监控等领域中&#xff0c;大分辨率图像的使用已经成为了一项不可或缺的技术。然而&#xff0c;大分辨率图像带来了巨大的计算和存储压力&#xff0c;同…...

【机器学习】机器学习的基本分类-半监督学习-Ladder Networks

Ladder Networks 是一种半监督学习模型&#xff0c;通过将无监督学习与监督学习相结合&#xff0c;在标记数据较少的情况下实现高效的学习。它最初由 A. Rasmus 等人在 2015 年提出&#xff0c;特别适合深度学习任务&#xff0c;如图像分类或自然语言处理。 核心思想 Ladder N…...

[react]小技巧, ts如何声明点击事件的类型

很简单, 鼠标放到事件上面就行了 如果想知道点击的是什么元素 ,打印他的nodename就行了 不过得断言为html元素才行 const handleClick (e: React.MouseEvent<HTMLDivElement, MouseEvent>) > {console.log(current, (e.target as HTMLElement).nodeName);}; 为什么…...

智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之9 重新开始 之2

本文要点 对程序设计而言&#xff1a;前者基于一个自上而下的 分类体系--&#xff08;生物遗传基因&#xff09;&#xff0c;后者者需要一个收集差异的自下而上的差异继承路径--&#xff08;系统继承源流&#xff09; 就是 广义和狭义 分类学。 共性对齐 和 差异收集 正是两者…...

【从零开始】11. LLaMA-Factory 微调 Qwen 模型(番外篇)

书接上回&#xff0c;在完成了 RAGChecker 测试后&#xff0c;离 RAG 应用真正发布还差最后一步 - 基础信息指令微调。考虑到模型还是需要具备一定程度的“自我认知”&#xff0c;因此需要将公司信息“嵌入”到模型里面的。为此&#xff0c;我选择了 LLaMA-Factory&#xff08;…...

WPF使用ContentControl控件实现区域导航,并使用Prism依赖注入优化

背景&#xff1a;使用ContentControl控件实现区域导航是有Mvvm框架的WPF都能使用的&#xff0c;不限于Prism 主要是将ContenControl控件的Content内容在ViewModel中切换成不同的用户控件 下面是MainViewModel&#xff1a; private object body;public object Body {get { retu…...

JavaWeb——MySQL-DML(1/3)-添加数据insert(DML 操作概述、INSERT 语句插入数据、语句演示、总结)

目录 DML 操作概述 INSERT 语句插入数据 INSERT 语句基础语法 INSERT 语句演示 注意事项 总结 DML 操作概述 DML 简介 DML&#xff08;Data Manipulation Language&#xff09;即数据操作语言&#xff0c;用于对数据库表中的数据进行增删改操作&#xff0c;包括添加数据&…...

经验证:将数据从索尼传输到Android的 4 种方法

概括 像Android Galaxy S20 这样的新型Android智能手机很酷&#xff0c;但除了将数据从索尼传输到Android之外。众所周知&#xff0c;旧的索尼手机上存储着大量的文件&#xff0c;因此将数据从旧的索尼手机传输到新的Android手机非常重要。为了解决这个问题&#xff0c;我们做…...

嵌入式应用实例→电子产品量产工具→UI界面的绘制和测试

前言 之前已经在博文https://blog.csdn.net/wenhao_ir/article/details/144747714中实现了用Freetype在LCD屏上绘制字符&#xff0c;本篇博文我们利用Freetype实现UI界面的绘制。 头文件include\ui.h的分析 头文件内的代码 #ifndef _UI_H #define _UI_H#include <common…...

如何删除 Docker 中的悬虚镜像?

在 Docker 中&#xff0c;悬虚镜像&#xff08;Dangling Images&#xff09;是指那些没有 标签 且没有被任何容器使用的镜像。这些镜像通常是由于构建过程中生成的中间层镜像或未正确清理的镜像残留。删除悬虚镜像可以释放磁盘空间并保持 Docker 环境的整洁。 1. 列出悬虚镜像…...

el-table树形懒加载展开改为点击行展开

思路&#xff1a;获取el-table中小箭头&#xff0c;然后调它的click事件&#xff01; <el-tablerow-click"getOpenDetail":row-class-name"tableRowClassName">// 点击当前行展开节点getOpenDetail(row, column, event) {// 如果是叶子节点或点击的是…...

【Ubuntu】Ubuntu server 18.04 搭建Slurm并行计算环境(包含NFS)

Ubuntu server 18.04 搭建Slurm并行计算环境&#xff08;包含NFS&#xff09; 一、Munge 认证模块 1.1、安装 munge 主节点和子节点都安装munge #安装 sudo apt update && sudo apt install munge libmunge-dev#设置开机启动 sudo systemctl enable munge sudo syste…...

高并发场景下的秒杀系统架构设计与实现

引言 秒杀系统是一种高并发场景的典型应用&#xff0c;广泛存在于电商平台、抢票系统和促销活动中。秒杀活动的特点是短时间内吸引大量用户同时访问并尝试抢购商品&#xff0c;这对系统的高并发处理能力、稳定性和用户体验提出了极高的要求。 在秒杀系统中&#xff0c;常见的…...

搭建开源版Ceph分布式存储

系统&#xff1a;Rocky8.6 三台2H4G 三块10G的硬盘的虚拟机 node1 192.168.2.101 node2 192.168.2.102 node3 192.168.2.103 三台虚拟机环境准备 1、配置主机名和IP的映射关系 2、关闭selinux和firewalld防火墙 3、配置时间同步且所有节点chronyd服务开机自启 1、配置主机名和…...

QT----------多媒体

实现思路 多媒体模块功能概述&#xff1a; QT 的多媒体模块提供了丰富的功能&#xff0c;包括音频播放、录制、视频播放和摄像头操作等。 播放音频&#xff1a; 使用 QMediaPlayer 播放完整的音频文件。使用 QSoundEffect 播放简短的音效文件。 录制音频&#xff1a; 使用 QMe…...

选择器(结构伪类选择器,伪元素选择器),PxCook软件,盒子模型

结构为类选择器 伪元素选择器 PxCook 盒子模型 (内外边距&#xff0c;边框&#xff09; 内外边距合并&#xff0c;塌陷问题 元素溢出 圆角 阴影: 模糊半径&#xff1a;越大越模糊&#xff0c;也就是越柔和 案例一&#xff1a;产品卡片 <!DOCTYPE html> <html lang&q…...

Vue2/Vue3 响应式原理对比指南

Vue2/Vue3 响应式原理对比指南 1. 基本实现原理 1.1 Vue2 响应式实现 (Object.defineProperty) // Vue2 响应式核心实现 function defineReactive(obj, key, val) {// 递归处理嵌套对象observe(val);const dep new Dep();Object.defineProperty(obj, key, {get() {// 依赖收…...

FastExcel:超越EasyExcel的新一代Excel处理工具

简介 FastExcel是由原EasyExcel作者在阿里巴巴宣布停止维护EasyExcel之后推出的升级版框架。它继承了EasyExcel的所有优点&#xff0c;并且在性能和功能上进行了显著的提升和创新。 FastExcel的特点 高性能读写&#xff1a;FastExcel专注于性能优化&#xff0c;能够高效处理…...

大模型系列17-RAGFlow搭建本地知识库

大模型系列17-RAGFlow搭建本地知识库 安装ollama安装open-wehui安装并运行ragflowRAG&#xff08;检索、增强、生成&#xff09;RAG是什么RAG三过程RAG问答系统构建步骤向量库构建检索模块生成模块 RAG解决LLM的痛点 使用ragflow访问ragflow配置ollama模型添加Embedding模型添加…...

常用的mac软件下载地址

目录 iRightMouse Pro&#xff08;超级右键&#xff09; xmind&#xff08;思维导图&#xff09; Parallels Desktop&#xff08;虚拟机工具&#xff09; Paste&#xff08;跨平台复制粘贴&#xff09; AutoSwitchInput Pro&#xff08;自动切换输入法&#xff09; Snipa…...

基于51单片机和16X16LED点阵屏(74HC138和74HC595驱动)的小游戏《贪吃蛇》

目录 系列文章目录前言一、效果展示二、原理分析三、各模块代码1、定时器02、自制八位独立按键3、点阵屏模块 四、主函数总结 系列文章目录 前言 《贪吃蛇》&#xff0c;一款经典的、怀旧的小游戏&#xff0c;单片机入门必写程序。 以《贪吃蛇》为载体&#xff0c;熟悉各种屏…...

python中常用的内置函数介绍

python中常用的内置函数介绍 1. print()2. len()3. type()4. str(), int(), float()5. list(), tuple(), set(), dict()6. range()7. sum()8. max(), min()9. sorted()10. zip()11. enumerate()12. map()13. filter()14. any(), all()15. abs()16. pow()17. round()18. ord(), …...

【微服务】Spring Cloud Config解决的问题和案例

文章目录 强烈推荐引言解决问题1. 配置管理的集中化2. 配置的版本控制3. 环境特定配置4. 配置的动态刷新5. 安全管理敏感数据6. 配置的一致性 组件1. **配置服务器&#xff08;Config Server&#xff09;**2. **配置客户端&#xff08;Config Client&#xff09;** 配置示例配置…...

华为OD机试E卷 --最小的调整次数--24年OD统一考试(Java JS Python C C++)

文章目录 题目描述输入描述输出描述用例题目解析JS算法源码Java算法源码python算法源码c算法源码c++算法源码题目描述 有一个特异性的双端队列一,该队列可以从头部或尾部添加数据,但是只能从头部移出数据。 小A依次执行2n个指令往队列中添加数据和移出数据。其中n个指令是添…...

Oracle Dataguard(主库为 Oracle 11g 单节点)配置详解(2):配置主数据库

Oracle Dataguard&#xff08;主库为 Oracle 11g 单节点&#xff09;配置详解&#xff08;2&#xff09;&#xff1a;配置主数据库 目录 Oracle Dataguard&#xff08;主库为 Oracle 11g 单节点&#xff09;配置详解&#xff08;2&#xff09;&#xff1a;配置主数据库一、配置…...

慧集通iPaaS集成平台低代码训练-实践篇

练习使用帐号信息&#xff1a; 1.致远A8平台&#xff08;请自行准备测试环境&#xff09; 慧集通连接器配置相关信息 访问地址&#xff1a; rest账号&#xff1a;rest rest密码&#xff1a; OA账号&#xff1a; 2.云星空&#xff08;请自行准备测试环境&#xff09; 连接…...

TDengine 如何进行高效数据建模

1.背景 数据建模对于数据库建立后整体高效运行非常关键&#xff0c;不同建模方式&#xff0c;可能会产生相差几倍的性能差别 2. 建库 建模在建库阶段应考虑几下几点&#xff1a; 建多少库 根据业务情况确定建库个数&#xff0c;TDengine 不支持跨库查询&#xff0c;如果业…...

HarmonyOS NEXT应用开发实战:一分钟写一个网络接口,JsonFormat插件推荐

在开发鸿蒙操作系统应用时&#xff0c;网络接口的实现往往是一个繁琐且重复的过程。为了提高开发效率&#xff0c;坚果派(nutpi.net)特别推出了一个非常实用的插件——JsonFormat。这款插件的主要功能是将JSON格式的数据直接转换为arkts的结构定义&#xff0c;让我们在编写接口…...

基于动力学的MPC控制器设计盲点解析

文章目录 Apollo MPC控制器的设计架构误差模型和离散化预测模型推导目标函数和约束设计优化求解优化OSQP求解器参考文献 Apollo MPC控制器的设计架构 误差模型和离散化 状态变量和控制变量 1、Apollo MPC控制器中状态变量主要有如下6个 matrix_state_ Matrix::Zero(basic_stat…...