Java使用CompletableFuture实现异步编程

 更新时间:2025年01月16日 11:08:07   作者:加瓦点灯  
在现代 Java 开发中,异步编程是一项重要技能,而 CompletableFuture 是从 Java 8 开始提供的一个功能强大的工具,用于简化异步任务的编写和组合,本文将详细介绍 CompletableFuture 的基本使用和一些常见的应用场景,需要的朋友可以参考下

1. 为什么选择 CompletableFuture?

传统的异步编程通常依赖于回调或 Future,但这些方法存在一些缺陷:

  • 回调地狱:嵌套层级多,代码难以阅读。
  • Future 的 get() 方法是阻塞的,无法真正实现非阻塞式编程。

CompletableFuture 的优势在于:

  • 支持非阻塞操作。
  • 提供丰富的 API 用于任务的组合和处理。
  • 更好的错误处理机制。

2. 基本用法

创建一个 CompletableFuture

import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
    public static void main(String[] args) {
        // 创建一个异步任务
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(1000); // 模拟耗时操作
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            return "Hello, CompletableFuture!";
        });

        // 非阻塞地获取结果
        future.thenAccept(result -> System.out.println("Result: " + result));

        System.out.println("Main thread is not blocked");

        // 防止主线程退出过早
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

输出

Main thread is not blocked
Result: Hello, CompletableFuture!

3. 任务组合

thenApply: 转换结果

thenApply 方法用于将异步任务的结果转换为另一种类型。

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> "42")
    .thenApply(Integer::parseInt)
    .thenApply(num -> num * 2);

future.thenAccept(result -> System.out.println("Final Result: " + result));

thenCompose: 链式调用

thenCompose 用于在一个任务完成后启动另一个异步任务。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello")
    .thenCompose(s -> CompletableFuture.supplyAsync(() -> s + " World!"));

future.thenAccept(System.out::println);

thenCombine: 合并两个任务

thenCombine 用于合并两个独立的异步任务的结果。

CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> "Hello");
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "World");

CompletableFuture<String> result = future1.thenCombine(future2, (s1, s2) -> s1 + " " + s2);
result.thenAccept(System.out::println);

4. 异常处理

在异步任务中,异常处理非常重要。CompletableFuture 提供了多种方法来优雅地处理异常。

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

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    if (true) {
        throw new RuntimeException("Something went wrong");
    }
    return "Success";
}).exceptionally(ex -> {
    System.out.println("Exception: " + ex.getMessage());
    return "Default Value";
});

future.thenAccept(System.out::println);

handle: 处理结果和异常

handle 方法无论任务成功还是失败都会执行,并可以访问异常信息。

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    if (true) {
        throw new RuntimeException("Error occurred");
    }
    return "Success";
}).handle((result, ex) -> {
    if (ex != null) {
        System.out.println("Exception: " + ex.getMessage());
        return "Recovered from error";
    }
    return result;
});

future.thenAccept(System.out::println);

5. 实际应用场景

并发请求处理

在需要同时处理多个请求时,可以利用 allOf 或 anyOf 方法。

allOf: 等待所有任务完成

CompletableFuture<Void> allTasks = CompletableFuture.allOf(
    CompletableFuture.runAsync(() -> System.out.println("Task 1")),
    CompletableFuture.runAsync(() -> System.out.println("Task 2")),
    CompletableFuture.runAsync(() -> System.out.println("Task 3"))
);

allTasks.thenRun(() -> System.out.println("All tasks completed"));

anyOf: 任意任务完成即返回

CompletableFuture<Object> anyTask = CompletableFuture.anyOf(
    CompletableFuture.supplyAsync(() -> "Task 1 completed"),
    CompletableFuture.supplyAsync(() -> "Task 2 completed")
);

anyTask.thenAccept(result -> System.out.println("First completed: " + result));

6. 总结

CompletableFuture 是 Java 异步编程的强大工具,提供了丰富的 API 来实现任务的创建、组合和异常处理。通过熟练掌握 CompletableFuture,可以编写更加简洁高效的异步代码。

以上就是Java使用CompletableFuture实现异步编程的详细内容,更多关于Java CompletableFuture异步编程的资料请关注脚本之家其它相关文章!

相关文章

  • Java 反射机制详解及实例代码

    Java 反射机制详解及实例代码

    本文主要介绍Java 反射机制的知识,这里提供示例代码帮助大家学习理解此部分知识,有需要的小伙伴可以参考下
    2016-09-09
  • java生成随机字符串的两种方法

    java生成随机字符串的两种方法

    这篇文章主要为大家详细介绍了java生成随机字符串的两种方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-10-10
  • 带你快速搞定java IO

    带你快速搞定java IO

    这篇文章主要介绍了Java IO流 文件传输基础的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下,希望能给你带来帮助
    2021-07-07
  • 详解SpringCloudGateway内存泄漏问题

    详解SpringCloudGateway内存泄漏问题

    这篇文章主要介绍了详解SpringCloudGateway内存泄漏问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-07-07
  • springboot+springsecurity如何实现动态url细粒度权限认证

    springboot+springsecurity如何实现动态url细粒度权限认证

    这篇文章主要介绍了springboot+springsecurity如何实现动态url细粒度权限认证的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-06-06
  • Java基础篇_有关接口和抽象类的几道练习题(分享)

    Java基础篇_有关接口和抽象类的几道练习题(分享)

    下面小编就为大家带来一篇Java基础篇_有关接口和抽象类的几道练习题(分享)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-06-06
  • 浅谈java中静态方法的重写问题详解

    浅谈java中静态方法的重写问题详解

    本篇文章是对java中静态方法的重写问题进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • Junit Mockito实现单元测试方法介绍

    Junit Mockito实现单元测试方法介绍

    JUnit是用于编写和运行可重复的自动化测试开源测试项目框架,这样可以保证我们的代码按与其工作。JUnit可广泛用于工业和作为支架(从命令行)或IDE(如IDE)内单独的java程序
    2022-09-09
  • Scala中的mkString的具体使用方法

    Scala中的mkString的具体使用方法

    这篇文章主要介绍了Scala中的mkString的具体方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-06-06
  • Seata集成Mybatis-Plus解决多数据源事务问题

    Seata集成Mybatis-Plus解决多数据源事务问题

    当进行业务操作时,订单发生异常 ,进行了回滚操作,因为在不同的数据库实例中,余额却扣除成功,此时发现数据不一致问题,本文给大家介绍Seata集成Mybatis-Plus解决多数据源事务问题,感兴趣的朋友一起看看吧
    2023-11-11

最新评论