首页 > 编程语言 >如何使用Java CompletableFuture

如何使用Java CompletableFuture

时间:2024-08-16 10:48:42浏览次数:14  
标签:异步 Java 如何 任务 future CompletableFuture result supplyAsync

Java 的 CompletableFuture 是处理异步编程的利器。它不仅简化了异步任务的执行,还提供了丰富的 API 来支持任务的组合、异常处理、以及多任务并行。

1. CompletableFuture 的基础概念

CompletableFuture 是 Java 8 中引入的,属于 java.util.concurrent 包。它实现了 Future 接口,允许在异步计算完成后获得结果。与 Future 不同,CompletableFuture 不仅提供了阻塞式获取结果的方法,还允许你以非阻塞方式继续执行后续操作。

2. CompletableFuture 的创建方式

CompletableFuture 可以通过多种方式创建:

  • CompletableFuture.supplyAsync(Supplier<U> supplier):用于异步执行任务,并在完成后返回结果。

    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { // 模拟耗时任务 return "Task Result"; });
  • CompletableFuture.runAsync(Runnable runnable):用于异步执行任务,但不返回结果。

    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> { // 执行异步任务 System.out.println("Task Executed"); });
  • CompletableFuture.completedFuture(U value):返回一个已经完成的 CompletableFuture

    CompletableFuture<String> future = CompletableFuture.completedFuture("Already Completed");

3. CompletableFuture 的链式操作

链式操作是 CompletableFuture 的核心功能之一。你可以将多个异步操作串联起来,以流式的方式处理复杂的异步任务流。

  • thenApply(Function<U, V> fn):在前一个任务完成后,使用其结果执行另一个任务,并返回一个新的 CompletableFuture

    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello") .thenApply(result -> result + ", World!");
  • thenAccept(Consumer<U> action):接受前一个任务的结果,并执行某个操作,但不返回新的 CompletableFuture

    CompletableFuture.supplyAsync(() -> "Hello") .thenAccept(System.out::println); // 输出 "Hello"
  • thenRun(Runnable action):在前一个任务完成后,执行一个无参的操作。

    CompletableFuture.supplyAsync(() -> "Hello") .thenRun(() -> System.out.println("Task Completed"));

4. 任务的组合

CompletableFuture 提供了多种方式来组合多个异步任务。

  • thenCombine(CompletableFuture<U> other, BiFunction<T,U,V> fn):将两个 CompletableFuture 的结果组合在一起。

    CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello"); CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World"); CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 + " " + result2);
  • thenCompose(Function<U, CompletableFuture<V>> fn):在一个异步任务完成后,启动另一个异步任务,并返回其结果。

    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello") .thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " World"));
  • allOf(CompletableFuture<?>... futures):等待所有传入的 CompletableFuture 完成。

    CompletableFuture<Void> allFutures = CompletableFuture.allOf(future1, future2);
  • anyOf(CompletableFuture<?>... futures):一旦任意一个 CompletableFuture 完成,就结束等待。

    CompletableFuture<Object> anyOfFutures = CompletableFuture.anyOf(future1, future2);

5. 异常处理

处理异步任务中的异常是确保程序健壮性的重要步骤。CompletableFuture 提供了以下几种方式来处理异常:

  • exceptionally(Function<Throwable, ? extends U> fn):当异常发生时,使用默认值或处理逻辑。

    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { if (Math.random() > 0.5) { throw new RuntimeException("Failed Task"); } return "Success"; }).exceptionally(ex -> "Default Value");
  • handle(BiFunction<? super U, Throwable, ? extends V> fn):不论任务是否成功,都可以处理结果或异常。

    CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { if (Math.random() > 0.5) { throw new RuntimeException("Failed Task"); } return "Success"; }).handle((result, ex) -> { if (ex != null) { return "Error handled"; } return result; });

6. 使用自定义的 Executor

默认情况下,CompletableFuture 使用 ForkJoinPool.commonPool() 作为其线程池。你可以通过传递一个 Executor 来自定义线程池,以满足更复杂的性能需求。

Executor executor = Executors.newFixedThreadPool(5); CompletableFuture<Void> future = CompletableFuture.runAsync(() -> { // 执行异步任务 }, executor);

7. 实际应用场景

CompletableFuture 在实际开发中有很多应用场景,以下是几个典型的例子:

  • 并行处理多个 API 调用:在 Web 服务中,通常需要并行调用多个外部 API。使用 CompletableFuture 可以并行化这些调用,并在所有结果返回后进行处理。

  • 异步处理大数据:在大数据处理场景中,CompletableFuture 可以用于异步加载和处理数据,从而提高性能。

  • 事件驱动架构:在事件驱动的架构中,CompletableFuture 可以帮助处理异步事件流,确保事件之间的依赖关系正确处理。

8. 性能与优化建议

虽然 CompletableFuture 提供了强大的功能,但在使用时需要注意以下几点,以避免性能问题:

  • 避免过度的嵌套:复杂的异步链可能导致代码难以维护,建议将逻辑拆分成小的、易于理解的任务。
  • 合理使用线程池:确保使用适合的线程池配置,避免资源耗尽或线程饥饿。
  • 捕获和处理所有异常:在异步操作中,未处理的异常可能会被静默丢弃,建议始终使用 handleexceptionally 来捕获异常。

标签:异步,Java,如何,任务,future,CompletableFuture,result,supplyAsync
From: https://www.cnblogs.com/hsyxzx/p/18362465

相关文章

  • 学霸带你深入了解游戏如何展现文化多样性
    欢迎加入我在CSDN的社区【纽雪澳诺加海美德】引言全球化时代的文化交融在全球化的今天,文化的界限正在变得越来越模糊。游戏,作为一种广泛传播的娱乐形式,不仅仅是消遣的工具,更是文化交流和社会理解的桥梁。通过游戏,我们可以探索不同的世界,体验多样的文化,并与全球玩家建立联......
  • 如何解释无统计学显著性的结果?可以考虑用置信区间(CI)
    很多医学研究的目标是为了确定两种或多种治疗方法中哪一种治疗方法对某个特定的疾病更有效。一项研究的统计学把握度(power),又称检验效能,是指在一定程度上能够检验出具有真正治疗效果的概率,它高度依赖于研究的样本量大小。当采用回顾性观察性研究设计时,研究人员几乎无法控制样......
  • 基于Java中的SSM框架实现智慧医疗预约挂号管理系统项目【项目源码+论文说明】计算机毕
    基于Java中的SSM框架实现智慧医疗预约挂号管理系统演示摘要伴随着人们对医疗的关注度越来越高,对于信息化就医的发展也是当今社会发展的最为重要的问题之一。为了进一步的促进医疗事业的信息化发展工作,许多的大型的医院或者是医疗机构也在逐步的开展了信息化的就医和信息化......
  • 基于Java中的SSM框架实现在线订花系统项目【项目源码+论文说明】计算机毕业设计
    基于Java中的SSM框架实现在线订花系统演示摘要近年来,随着人们对于生活品质的重视度日益提升,鲜花的需求量也在不断增加同时带动了鲜花电商的飞速发展和应用,平台化的鲜花交易模式也逐渐从传统的鲜花销售转型为个性化鲜花定制。同时随着鲜花速递行业的不断成熟很多传统零售花......
  • 第七节:消息队列推拉模式选择、kafak如何提高吞吐量、超时关单和支付成功同时出现咋办
    一.        二.        三.         !作       者:Yaopengfei(姚鹏飞)博客地址:http://www.cnblogs.com/yaopengfei/声     明1:如有错误,欢迎讨论,请勿谩骂^_^。声     明2:原创博客请在转载......
  • 如何在 Git 中取消文件的跟踪
    如何在Git中取消文件的跟踪在使用Git进行版本控制时,文件可能最初被跟踪,但随着项目的发展,有时需要取消对这些文件的跟踪。本文介绍如何在不同情况下取消文件或目录的Git跟踪。1.取消对已经被Git跟踪的文件的跟踪如果某个文件已经添加到Git并被提交,但现在不希望Git......
  • Java获取PPT内容的完整指南
    在现代企业和教育环境中,PowerPoint(PPT)作为一种流行的演示文稿工具,被广泛应用于各种场合。随着数字化转型的推进,越来越多的企业希望能够自动化处理PPT文件,例如提取内容、分析数据和生成报告等。本文将介绍如何使用Java获取PPT内容,包括相关的库、代码示例以及最佳实践。一、Java......
  • 【Java】Word题库解析
    一、需求场景:一共四种题型,单选、多选、判断、简答题目构成要素:题目、选项、答案、解析一种题型一个Word文档存放,需要把这些题目写入DB维护 二、题库格式:单选案例:多选案例: 判断案例:简答题案例:可以看出,单选,多选和判断都是一样的- 题目有数字和点开头,并设置了标题......
  • 0-JavaScript入门
    1.1JS用途JavaScript属于一门脚本语言,可用于前端给网页添加一些动态效果。也可用于node平台,开发服务器React、Vue框架底层也是通过JS实现1.2JS组成前端分为三层层次用途HTML(结构层)利用语义化标签搭建网页CSS(样式层)利用样式进行美化网页、进行网页布局J......
  • 用JavaScript做超级玛丽小游戏
    一、前言前几天用JS实现扫雷和贪吃蛇(通过HTML的DOM节点实现基本界面,界面背景简单,交互简单)。比较复杂的是植物大战僵尸,不同的关卡设置单独的函数。所以还比较难。超级玛丽通过canvas实现背景,交互很复杂,功能很多,JS代码完全是有汇编语言反编译成C语言,然后把C语言转换成JS实现的......