JUC-CompletableFuture

devtools/2024/10/11 0:14:52/

1. CompletableFuture 简介

  • JUC 中提供的一个实现异步编程的工具类。实现了 FutureCompletionStage 两个接口,主要用作于创建,组合,处理多个异步任务
  • 核心思想是 异步任务的链式处理

2. CompletableFuture 与 Future 的区别

传统的 Future 接口在获取结果时,如果任务未完成,会阻塞,直到任务完成,或超时。 Future缺点如下

  1. 无法主动通知任务完成

    只能通过手动调用 get 方法 来阻塞线程获取结果

  2. 无法进行任务组合

    多个 Future 任务不能组合在一起进行复杂的依赖处理

  3. 没有回调机制

CompletableFuture 引入了 非阻塞回调机制

3. CompletableFuture 常用 API

3.1 创建 CompletableFuture 实例对象的方法

  1. CompletableFuture.supplyAsync()
    • 有返回值的
  2. CompletableFuture.runAsync()
    • 无返回结果

这两个方法,都可以传入自定义线程池

在这里插入图片描述
在这里插入图片描述

3.2 组合与处理异步结果

  1. 基本回调方法

    1. thenApply(Function)

      当任务完成时,应用指定的函数对结果进行转换,并返回一个新的 CompletableFuture

      java">future.thenApply(result -> result + " processed")
      
    2. thenAccept(Consumer)

      任务完成时,执行指定的动作,对结果进行消费,无返回值

      java">future.thenAccept(result -> System.out.println("Result: " + result))
      
    3. thenRun(Runnable)

      任务完成时,执行一个 Runnable, 但不处理结果

      java">future.thenRun(() -> System.out.println("Task finished"))
      
  2. 合并与组合任务

    1. thenCombine()

      合并两个独立的 CompletableFuture,当都完成时,执行一个 BiFunction 进行处理,并返回一个新的 CompletableFuture

      java">future1.thenCombine(future2, (res1, res2) -> res1 + res2)
      
    2. thenCompose()

      类似于 flatMap,将两个 CompletableFuture 链接起来,第一个 CompletableFuture 完成时,将其结果作为输入参数交给下一个 CompletableFuture。

      java">future1.thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " combined"))
      
    3. anyOf() 和 allOf()

      • anyOf():当任意一个 CompletableFuture 完成时返回(常用于“只要有一个任务完成”时)。
      • allOf():当所有 CompletableFuture 都完成时返回(常用于“等待所有任务完成”时)。
  3. 异常处理

    a. exceptionally(Function<Throwable, ? extends T>)

    如果 CompletableFuture 执行期间抛出了异常,则使用指定的函数处理异常,并返回一个默认值。

    java">future.exceptionally(ex -> "Error occurred: " + ex.getMessage())
    

    b. handle(BiFunction<T, Throwable, R>)

    无论任务成功或失败,均会触发该方法,接收 result 和 Throwable 两个参数。

    java">future.handle((result, ex) -> ex == null ? result : "Error: " + ex.getMessage())
    
  4. 阻塞获取结果

尽管 CompletableFuture 更推荐使用回调方法处理结果,但有时我们需要阻塞获取最终结果,可以使用以下方法:

  • get():阻塞等待,直到 CompletableFuture 完成。
  • get(long timeout, TimeUnit unit):带超时限制的阻塞获取。
  • join():与 get() 类似,但不会抛出 Checked Exception。

4. CompletableFuture 的应用场景

4.1 异步任务的链式处理

使用 thenApply()、thenAccept() 和 thenRun() 方法,可以将多个任务串联起来进行顺序执行,实现异步任务的链式处理。

4.2 并行任务的合并与汇总

CompletableFuture.allOf() 可以用于等待所有任务完成,thenCombine() 和 thenCompose() 可以将多个异步任务的结果合并。

4.3 异常处理与结果回退

使用 exceptionally()、handle() 等方法,可以优雅地处理异步任务执行过程中的异常情况。

4.4 异步任务的超时控制

可以通过 orTimeout() 和 completeOnTimeout() 方法实现对异步任务的超时控制。

5. 代码示例

java">import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;public class CompletableFutureExample {public static void main(String[] args) throws ExecutionException, InterruptedException {// 创建一个异步任务CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}return "Hello";});// 创建另一个异步任务,并将两个结果进行合并CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}return "World";});// 合并两个任务结果CompletableFuture<String> combinedFuture = future1.thenCombine(future2, (res1, res2) -> res1 + " " + res2);// 处理合并后的结果combinedFuture.thenAccept(result -> System.out.println("Result: " + result));// 异常处理CompletableFuture<String> exceptionHandledFuture = combinedFuture.exceptionally(ex -> "Error: " + ex.getMessage());// 阻塞获取最终结果System.out.println("Final Result: " + exceptionHandledFuture.get());}
}

http://www.ppmy.cn/devtools/123888.html

相关文章

【解决】虚拟机VMTool安装程序无法继续,Microsoft Runtime DLL安装程序未能完成安装

这个问题的原因是系统安装服务没有开启 打开任务管理器-服务-打开服务 找到windows installer 服务&#xff0c;开启即可

CMakeLists.txt关键字查漏补缺

target_link_libraries 用于指定目标&#xff08;如可执行文件或库&#xff09;要链接的库 cmake_minimum_required(VERSION 3.10)# 设置项目名称 project(my_project)# 添加可执行文件 add_executable(my_executable main.cpp)# 链接外部库 target_link_libraries(my_executa…

FreeRTOS学习总结

背景&#xff1a;在裸机开发上&#xff0c;有时候我们需要等待某个信号或者需要延迟时&#xff0c;CPU的运算是白白浪费掉了的&#xff0c;CPU的利用率并不高&#xff0c;我们希望当一个函数在等待的时候&#xff0c;可以去执行其他内容&#xff0c;提高CPU的效率&#xff0c;同…

JVM系列(二) -类的加载过程介绍

一、背景介绍 我们知道 Java 是先通过编译器将.java类文件转成.class字节码文件&#xff0c;然后再通过虚拟机将.class字节码文件加载到内存中来实现应用程序的运行。 那么虚拟机是什么时候加载class文件&#xff1f;如何加载class文件&#xff1f;class文件进入到虚拟机后发…

javascript学习笔记

参考链接&#xff1a;JavaScript 教程 | 菜鸟教程 一、javascript输出显示数据 window 对象 定义: window 对象代表浏览器窗口或标签页。它是 JavaScript 的全局对象&#xff0c;也是全局作用域的根。功能: 提供对浏览器窗口的控制&#xff0c;比如可以修改窗口大小、位置等…

第三章 RabbitMQ安装

目录 一、Mac RabbitMQ安装 1.1. 安装Homebrew 1.2. 安装RabbitMQ 1.3. 启动RabbitMQ服务 1.4. 访问RabbitMQ管理界面 1.5. 停止RabbitMQ 二、Linux RabbitMQ安装 2.1. 安装仓库和依赖包 2.2. 安装RabbitMQ 2.3. 启动RabbitMQ 2.4. 设置RabbitMQ服务开机自启 2.5. …

多线程-初阶(2)BlockingQueueThreadPoolExecutor

学习目标&#xff1a; 熟悉wait和notify的线程休眠和启动 熟悉多线程的基本案例 1.单例模式的两种设置模式:懒汉模式和饿汉模式 2.阻塞队列(生产者消费者模型) 3.线程池 4.定时器 1.wait和notify 由于线程之间是抢占式执⾏的, 因此线程之间执⾏的先后顺序难以预知. 但是…

4.STM32-中断

STM32-中断 需求&#xff1a;红灯每两秒进行闪烁&#xff0c;按键key1控制绿灯亮灭 简单的程序代码无法满足要求 如何让STM32既能执行HAL_DELAY这种耗时的任务&#xff0c;同时又能快速响应按键按下这种突发情况呢 设置中断步骤 1.接入中断 将KEY1输入模式由原先的GPIO_In…