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的区别
| 特性 | Future | CompletableFuture |
|---|---|---|
| 异步计算结果的获取 | 通过 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 类是并发编程中一个非常重要的工具。它主要用于表示一个异步计算的结果,允许你在计算完成后获取结果或处理异常。Java 的 Future 也常常与线程池(如 ExecutorService)结合使用,用来执行并行任务&…...
如何通过深度学习提升大分辨率图像预测准确率?
随着科技的不断进步,图像处理在各个领域的应用日益广泛,特别是在医疗影像、卫星遥感、自动驾驶、安防监控等领域中,大分辨率图像的使用已经成为了一项不可或缺的技术。然而,大分辨率图像带来了巨大的计算和存储压力,同…...
【机器学习】机器学习的基本分类-半监督学习-Ladder Networks
Ladder Networks 是一种半监督学习模型,通过将无监督学习与监督学习相结合,在标记数据较少的情况下实现高效的学习。它最初由 A. Rasmus 等人在 2015 年提出,特别适合深度学习任务,如图像分类或自然语言处理。 核心思想 Ladder N…...
[react]小技巧, ts如何声明点击事件的类型
很简单, 鼠标放到事件上面就行了 如果想知道点击的是什么元素 ,打印他的nodename就行了 不过得断言为html元素才行 const handleClick (e: React.MouseEvent<HTMLDivElement, MouseEvent>) > {console.log(current, (e.target as HTMLElement).nodeName);}; 为什么…...
智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之9 重新开始 之2
本文要点 对程序设计而言:前者基于一个自上而下的 分类体系--(生物遗传基因),后者者需要一个收集差异的自下而上的差异继承路径--(系统继承源流) 就是 广义和狭义 分类学。 共性对齐 和 差异收集 正是两者…...
【从零开始】11. LLaMA-Factory 微调 Qwen 模型(番外篇)
书接上回,在完成了 RAGChecker 测试后,离 RAG 应用真正发布还差最后一步 - 基础信息指令微调。考虑到模型还是需要具备一定程度的“自我认知”,因此需要将公司信息“嵌入”到模型里面的。为此,我选择了 LLaMA-Factory(…...
WPF使用ContentControl控件实现区域导航,并使用Prism依赖注入优化
背景:使用ContentControl控件实现区域导航是有Mvvm框架的WPF都能使用的,不限于Prism 主要是将ContenControl控件的Content内容在ViewModel中切换成不同的用户控件 下面是MainViewModel: private object body;public object Body {get { retu…...
JavaWeb——MySQL-DML(1/3)-添加数据insert(DML 操作概述、INSERT 语句插入数据、语句演示、总结)
目录 DML 操作概述 INSERT 语句插入数据 INSERT 语句基础语法 INSERT 语句演示 注意事项 总结 DML 操作概述 DML 简介 DML(Data Manipulation Language)即数据操作语言,用于对数据库表中的数据进行增删改操作,包括添加数据&…...
经验证:将数据从索尼传输到Android的 4 种方法
概括 像Android Galaxy S20 这样的新型Android智能手机很酷,但除了将数据从索尼传输到Android之外。众所周知,旧的索尼手机上存储着大量的文件,因此将数据从旧的索尼手机传输到新的Android手机非常重要。为了解决这个问题,我们做…...
嵌入式应用实例→电子产品量产工具→UI界面的绘制和测试
前言 之前已经在博文https://blog.csdn.net/wenhao_ir/article/details/144747714中实现了用Freetype在LCD屏上绘制字符,本篇博文我们利用Freetype实现UI界面的绘制。 头文件include\ui.h的分析 头文件内的代码 #ifndef _UI_H #define _UI_H#include <common…...
如何删除 Docker 中的悬虚镜像?
在 Docker 中,悬虚镜像(Dangling Images)是指那些没有 标签 且没有被任何容器使用的镜像。这些镜像通常是由于构建过程中生成的中间层镜像或未正确清理的镜像残留。删除悬虚镜像可以释放磁盘空间并保持 Docker 环境的整洁。 1. 列出悬虚镜像…...
el-table树形懒加载展开改为点击行展开
思路:获取el-table中小箭头,然后调它的click事件! <el-tablerow-click"getOpenDetail":row-class-name"tableRowClassName">// 点击当前行展开节点getOpenDetail(row, column, event) {// 如果是叶子节点或点击的是…...
【Ubuntu】Ubuntu server 18.04 搭建Slurm并行计算环境(包含NFS)
Ubuntu server 18.04 搭建Slurm并行计算环境(包含NFS) 一、Munge 认证模块 1.1、安装 munge 主节点和子节点都安装munge #安装 sudo apt update && sudo apt install munge libmunge-dev#设置开机启动 sudo systemctl enable munge sudo syste…...
高并发场景下的秒杀系统架构设计与实现
引言 秒杀系统是一种高并发场景的典型应用,广泛存在于电商平台、抢票系统和促销活动中。秒杀活动的特点是短时间内吸引大量用户同时访问并尝试抢购商品,这对系统的高并发处理能力、稳定性和用户体验提出了极高的要求。 在秒杀系统中,常见的…...
搭建开源版Ceph分布式存储
系统: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----------多媒体
实现思路 多媒体模块功能概述: QT 的多媒体模块提供了丰富的功能,包括音频播放、录制、视频播放和摄像头操作等。 播放音频: 使用 QMediaPlayer 播放完整的音频文件。使用 QSoundEffect 播放简短的音效文件。 录制音频: 使用 QMe…...
选择器(结构伪类选择器,伪元素选择器),PxCook软件,盒子模型
结构为类选择器 伪元素选择器 PxCook 盒子模型 (内外边距,边框) 内外边距合并,塌陷问题 元素溢出 圆角 阴影: 模糊半径:越大越模糊,也就是越柔和 案例一:产品卡片 <!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的所有优点,并且在性能和功能上进行了显著的提升和创新。 FastExcel的特点 高性能读写:FastExcel专注于性能优化,能够高效处理…...
大模型系列17-RAGFlow搭建本地知识库
大模型系列17-RAGFlow搭建本地知识库 安装ollama安装open-wehui安装并运行ragflowRAG(检索、增强、生成)RAG是什么RAG三过程RAG问答系统构建步骤向量库构建检索模块生成模块 RAG解决LLM的痛点 使用ragflow访问ragflow配置ollama模型添加Embedding模型添加…...
【杂谈】-递归进化:人工智能的自我改进与监管挑战
递归进化:人工智能的自我改进与监管挑战 文章目录 递归进化:人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管?3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制
在数字化浪潮席卷全球的今天,数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具,在大规模数据获取中发挥着关键作用。然而,传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时,常出现数据质…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习)
Aspose.PDF 限制绕过方案:Java 字节码技术实战分享(仅供学习) 一、Aspose.PDF 简介二、说明(⚠️仅供学习与研究使用)三、技术流程总览四、准备工作1. 下载 Jar 包2. Maven 项目依赖配置 五、字节码修改实现代码&#…...
WebRTC从入门到实践 - 零基础教程
WebRTC从入门到实践 - 零基础教程 目录 WebRTC简介 基础概念 工作原理 开发环境搭建 基础实践 三个实战案例 常见问题解答 1. WebRTC简介 1.1 什么是WebRTC? WebRTC(Web Real-Time Communication)是一个支持网页浏览器进行实时语音…...
手机平板能效生态设计指令EU 2023/1670标准解读
手机平板能效生态设计指令EU 2023/1670标准解读 以下是针对欧盟《手机和平板电脑生态设计法规》(EU) 2023/1670 的核心解读,综合法规核心要求、最新修正及企业合规要点: 一、法规背景与目标 生效与强制时间 发布于2023年8月31日(OJ公报&…...
