【CompletableFuture】异步编程

CompletableFuture异步编程

  • CompletableFuture介绍
  • 与传统 Future 的对比
  • 使用方法
    • 1. 使用 supplyAsync(有返回值)
    • 使用 runAsync(无返回值)
    • 指定自定义线程池
  • 处理异步结果
    • 1. thenApply:转换结果
    • 2.thenAccept:消费结果
    • 3.thenRun:完成后执行操作
  • 组合任务
    • 1. thenCompose:串联两个任务
    • 2. thenCombine:合并两个任务结果
    • 3. allOf:等待所有任务完成
    • 4. anyOf:任意一个任务完成
  • 异常处理
    • 1. exceptionally:捕获异常并返回默认值
    • 2. handle:无论成功/失败都处理
    • 3. whenComplete:记录日志但不修改结果
  • 完整示例:链式调用 + 异常处理
  • 关键点总结

CompletableFuture介绍

1.基础概念

CompletableFuture 是 Java 8 引入的一个类,用于表示异步计算的结果。它实现了 Future 接口,但比传统的 Future 更强大,支持:

  • 非阻塞操作:通过回调函数处理结果,无需手动调用 get() 阻塞线程。

  • 链式编程:将多个异步任务串联或并联,形成复杂的执行流水线。

  • 异常处理:提供统一的异常捕获和恢复机制。

2. 核心思想

  • 异步编程:将耗时的操作(如I/O、网络请求)交给其他线程执行,主线程继续处理其他任务。

  • 函数式风格:通过 thenApply、thenAccept 等方法,以声明式的方式组合任务。

3. 关键特点

  • 回调驱动:任务完成后自动触发后续操作。

  • 线程池集成:支持自定义线程池,避免资源竞争。

  • 结果依赖管理:轻松处理多个任务之间的依赖关系(如A任务的结果是B任务的输入)。

与传统 Future 的对比

特性FutureCompletableFuture
结果获取阻塞调用 get()非阻塞回调(thenAccept)
任务组合需要手动轮询链式调用(thenApply、thenCompose)
异常处理需在调用代码中处理内置 exceptionally、handle
线程控制依赖 ExecutorService支持自定义线程池
适用场景简单的异步任务复杂的异步流水线

使用方法

1. 使用 supplyAsync(有返回值)

public class MyThreadTest {public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {// 模拟耗时操作try {Thread.sleep(1000);}catch (InterruptedException e){e.printStackTrace();}return "00";});// 获取结果(阻塞)String result = future.get();System.out.println("result:"+result);}
}

使用 runAsync(无返回值)

public class MyThreadTest {public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("sleep 1m");});//等待任务完成completableFuture.get();}
}

指定自定义线程池

public class MyThreadTest {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService executor = Executors.newFixedThreadPool(2);CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {return "Custom Thread Pool";}, executor);String s = future.get();System.out.println(s);}
}

处理异步结果

1. thenApply:转换结果

thenApply 方法用于在 CompletableFuture 完成时应用一个函数,并返回计算的结果。它返回一个新的 CompletableFuture,该 CompletableFuture 的类型由函数返回值的类型决定。
语法:

public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn);

示例:

public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello").thenApply(s -> s + " World");String s = future.get();System.out.println(s);}

输出
在这里插入图片描述

2.thenAccept:消费结果

thenAccept 方法用于在 CompletableFuture 完成时执行一个消费者(Consumer)操作,但不返回任何值(即它的返回类型是 void)。这通常用于执行一些副作用,比如打印日志、更新UI等,而不关心计算的结果。
语法:

public CompletableFuture<Void> thenAccept(Consumer<? super T> action);

示例:

public class MyThreadTest {public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> "Hello").thenAccept(s -> System.out.println("Result: " + s));future.get();}
}

输出
在这里插入图片描述

3.thenRun:完成后执行操作

public class MyThreadTest {public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> "Hello").thenRun(() -> System.out.println("Task finished"));future.get();}
}

输出
在这里插入图片描述

组合任务

1. thenCompose:串联两个任务

public class MyThreadTest {public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<String> future = CompletableFuture.supplyAsync(() ->{String a = "Hello";System.out.println(Thread.currentThread().getName() + "-a:" + a);return a;}).thenCompose(s -> CompletableFuture.supplyAsync(() -> {String r = " World";System.out.println(Thread.currentThread().getName() + "-r:" + r);return s + r;}));String s = future.get();// "Hello World"System.out.println(Thread.currentThread().getName() + "s:"+s);}
}

输出:
在这里插入图片描述

2. thenCombine:合并两个任务结果

public class MyThreadTest {public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {String h = "Hello";System.out.println(Thread.currentThread().getName() + " h:" + h);return h;});CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() ->{String w = " World";System.out.println(Thread.currentThread().getName() + " w:" + w);return w;});CompletableFuture<String> combined = future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2);String s = combined.get();System.out.println(Thread.currentThread().getName() + " s:" + s);}
}

输出:
在这里插入图片描述

3. allOf:等待所有任务完成

public class MyThreadTest {public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> "Task1");CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task2");CompletableFuture<Void> all = CompletableFuture.allOf(task1, task2);all.thenRun(() -> System.out.println("All tasks completed"));}
}

输出
在这里插入图片描述

4. anyOf:任意一个任务完成

public class MyThreadTest {public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<String> task1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(2000);}catch (InterruptedException e){e.printStackTrace();}return "Task1";});CompletableFuture<String> task2 = CompletableFuture.supplyAsync(() -> "Task2");CompletableFuture<Object> any = CompletableFuture.anyOf(task1, task2);any.thenAccept(result -> System.out.println("First result: " + result)); // 输出 "Task2"}
}

输出
在这里插入图片描述

异常处理

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

public class MyThreadTest {public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {if (true) throw new RuntimeException("Error!");return "Success";}).exceptionally(ex -> "Fallback Value");String s = future.get();// 返回 "Fallback Value"System.out.println(s);}
}

在这里插入图片描述

2. handle:无论成功/失败都处理

public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {if (new Random().nextBoolean()) throw new RuntimeException("Error!");return "Success";}).handle((result, ex) -> {if (ex != null) return "Fallback";return result;});}

3. whenComplete:记录日志但不修改结果

public class MyThreadTest {public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello").whenComplete((result, ex) -> {if (ex != null) ex.printStackTrace();else System.out.println("Result: " + result);});String s = future.get();System.out.println(s);}
}

完整示例:链式调用 + 异常处理

public class MyThreadTest {public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture.supplyAsync(() -> {// 步骤1:获取用户IDreturn 123;}).thenApply(userId -> {// 步骤2:根据用户ID查询名称if (userId == 123) return "Alice";else throw new IllegalArgumentException("Invalid User ID");}).thenApply(userName -> {// 步骤3:转换为大写return userName.toUpperCase();}).exceptionally(ex -> {// 统一异常处理System.out.println("Error: " + ex.getMessage());return "DEFAULT_USER";}).thenAccept(finalResult -> {System.out.println("Final Result: " + finalResult); // 输出 "ALICE" 或 "DEFAULT_USER"});}
}

输出
在这里插入图片描述

关键点总结

异步执行:使用 supplyAsync/runAsync 启动异步任务。

链式调用:通过 thenApply/thenAccept/thenRun 串联操作。

组合任务:thenCompose(依赖)和 thenCombine(并行)合并结果。

异常处理:优先使用 exceptionally 或 handle 提供容错。

线程池控制:避免使用默认线程池处理阻塞任务(如I/O)

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

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

相关文章

【TS学习】(23)理解类的双重角色

在 TypeScript 中&#xff0c;类&#xff08;class&#xff09;不仅是一个运行时的值&#xff08;即可以实例化对象的构造函数&#xff09;&#xff0c;同时也是一个类型声明。具体来说&#xff0c;类在 TypeScript 中既声明了值&#xff0c;也声明了类型&#xff0c;并且它的类…

IAP Firmware Upload Tools.exe IAP 网络固件升级教程

IAP是In Application Programming的简写&#xff0c;IAP升级可以被视为固件升级的一种形式,它是一种在应用程序运行过程中对固件进行更新的技术手段。允许MCU在运行过程中对MCU User Flash的部分区域进行烧写,目的是为了代替编程器对MCU烧录的依赖。 主程序UI 软件按钮说明&a…

Uniapp当中的async/await的作用

一、原始代码的行为&#xff08;使用 async/await&#xff09; const getUserMessagePlan async () > {// 等待两个异步操作完成const tabsList await message.getTagesList(); // 等待获取标签列表const tagsStateList await message.getTagsStateList(); // 等…

设计模式 Day 5:夯实观察者模式(Boost 实战精讲)

今天我们继续深入观察者模式的学习&#xff0c;不再局限于手写的抽象结构&#xff0c;而是聚焦于真实项目中如何使用成熟框架&#xff08;如 Boost.Signals2&#xff09;高效落地观察者模式。 本篇采用**“理论解析 问答讲解 实战用例”**结构&#xff0c;帮助你从设计思想到…

设计模式 Day 3:抽象工厂模式(Abstract Factory Pattern)详解

经过前两天的学习&#xff0c;我们已经掌握了单例模式与工厂方法模式&#xff0c;理解了如何控制实例个数与如何通过子类封装对象的创建逻辑。 今天&#xff0c;我们将进一步深入“工厂”体系&#xff0c;学习抽象工厂模式&#xff08;Abstract Factory Pattern&#xff09;&a…

MySQL:事务的理解

一、CURD不加控制&#xff0c;会有什么问题 &#xff08;1&#xff09;因为&#xff0c;MySQL里面存的是数据&#xff0c;所以很有可能会被多个客户访问&#xff0c;所以mysqld可能一次会接受到多个关于CURD的请求。&#xff08;2&#xff09;且mysql内部是采用多线程来完成数…

蓝桥杯刷题--宝石组合

在一个神秘的森林里&#xff0c;住着一个小精灵名叫小蓝。有一天&#xff0c;他偶然发现了一个隐藏在树洞里的宝藏&#xff0c;里面装满了闪烁着美丽光芒的宝石。这些宝石都有着不同的颜色和形状&#xff0c;但最引人注目的是它们各自独特的 “闪亮度” 属性。每颗宝石都有一个…

DAY06:【pytorch】图像增强

1、基本概念 数据增强&#xff0c;又称数据增广、数据扩增&#xff0c;是对训练集进行变换&#xff0c;使训练集更丰富&#xff0c;从而让模型更具泛化能力 2、裁剪 — — Crop 2.1 transforms.CenterCrop 功能&#xff1a;从图像中心裁剪图片 size&#xff1a;所需裁剪图…

mysql 禁止 读 某个 表

mysql 禁止 读 某个 表 mysql禁用某张表,禁用MySQL表的操作 https://shuyeidc.com/wp/89479.html MySQL严格禁止读取表如何避免数据泄露 https://www.kdun.cn/ask/394700.html select host,user from mysql.user; FLUSH PRIVILEGES; 1. MySQL严格禁止读取表如何避免数据泄露…

机器学习 从入门到精通 day_03

1. KNN算法-分类 1.1 样本距离判断 明可夫斯基距离&#xff1a;欧式距离&#xff0c;明可夫斯基距离的特殊情况&#xff1b;曼哈顿距离&#xff0c;明可夫斯基距离的特殊情况。 两个样本的距离公式可以通过如下公式进行计算&#xff0c;又称为欧式距离。 &#xff08;…

LeetCode 热题 100_零钱兑换(85_322_中等_C++)(动态规划)

LeetCode 热题 100_零钱兑换&#xff08;85_322&#xff09; 题目描述&#xff1a;输入输出样例&#xff1a;题解&#xff1a;解题思路&#xff1a;思路一&#xff08;动态规划&#xff09;&#xff1a; 代码实现代码实现&#xff08;思路一&#xff08;动态规划&#xff09;&a…

游戏盾IP可以被破解吗

游戏盾IP&#xff08;如上海云盾SDK、腾讯云游戏盾&#xff09;是专为游戏行业设计的高防服务&#xff0c;旨在抵御DDoS攻击、CC攻击等威胁。其安全性取决于​​技术架构、防护能力​​以及​​运维策略​​。虽然理论上没有绝对“无法破解”的系统&#xff0c;但游戏盾IP在合理…

SpringBoot实战1

SpringBoot实战1 一、开发环境&#xff0c;环境搭建-----创建项目 通过传统的Maven工程进行创建SpringBoot项目 &#xff08;1&#xff09;导入SpringBoot项目开发所需要的依赖 一个父依赖&#xff1a;&#xff08;工件ID为&#xff1a;spring-boot-starter-parent&#xf…

【软考-高级】【信息系统项目管理师】【论文基础】进度管理过程输入输出及工具技术的使用方法

定义 项目进度管理是为了保证项目按时完成&#xff0c;对项目中所需的各个过程进行管理的过程&#xff0c;包括规划进度、定义活动、活动优先级排序、活动持续时间、制定进度计划和控制进度。 管理基础 制定进度计划的一般步骤 选择进度计划方法&#xff08;如关键路径法&a…

【Linux】之【Get】 chroot 环境下安装deb包时 .postinst:行 9: 201 段错误 (核心已转储)ldconfig

背景 如题&#xff0c;在postinst文件中直接执行了ldconfig命令&#xff0c; chroot 环境下出错&#xff0c;安装失败 分析 chroot 环境下不能用 ldconfig 和 systemctl 但是&#xff1a;如果环境是 chroot&#xff0c;系统有可能没完整挂载 /proc、/dev、系统路径&#xff…

【论文精读与实现】EDC²-RAG:基于动态聚类的文档压缩方法提升检索增强生成RAG性能

🧠 向所有学习者致敬! “学习不是装满一桶水,而是点燃一把火。” —— 叶芝 我的博客主页: https://lizheng.blog.csdn.net 🌐 欢迎点击加入AI人工智能社区! 🚀 让我们一起努力,共创AI未来! 🚀 1. 论文核心思想 这篇由清华大学团队提出的EDC-RAG框架,针对当前…

OSPF接口的网络类型和不规则区域

网络类型(数据链路层所使用的协议所构建的二层网络类型) 1、MA --- 多点接入网络 BMA --- 支持广播的多点接入网络 NBMA --- 不支持广播的多点接入网络 2、P2P --- 点到点网络 以太网 --- 以太网最主要的特点是需要基于MAC地址进行物理寻址&#xff0c;主要是因为以太网接口所连…

HTTP代理:内容分发战场上的「隐形指挥官」

目录 一、技术本质&#xff1a;流量博弈中的「规则改写者」 二、战略价值&#xff1a;内容分发的「四维升级」 三、实战案例&#xff1a;代理技术的「降维打击」 四、未来进化&#xff1a;代理技术的「认知升级」 五、结语&#xff1a;代理技术的「战略觉醒」 在数字内容爆…

(2)网络学习之堡垒机

堡垒机和防火墙的区别&#xff1a; 1.功能定位 防火墙主要负责抵御外部攻击&#xff0c;就像一道坚固的城墙&#xff0c;防止黑客进入内部网络。堡垒机则专注于内部管理&#xff0c;监控和记录运维人员的操作行为&#xff0c;确保内部网络的安全。 2.部署位置与作用范围 防…

minio命令行客户端mc常见用法

安装minio命令行客户端mc https://min-io.cn/docs/minio/linux/reference/minio-mc-admin.html # Windows安装minio命令行客户端 choco install minio-client -y# Linux安装mc客户端 wget -c -P /usr/local/bin/ https://dl.min.io/client/mc/release/linux-amd64/mc # 赋予可…