多线程之CompletableFuture(中)

本文详细介绍了Java中CompletableFuture的异步方法,包括thenAcceptAsync、thenRunAsync、thenApplyAsync、whenCompleteAsync和handleAsync等方法的区别及使用场景,并通过示例代码展示了这些方法如何实现异步操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

thenAcceptAsync

Consumer 接收上个阶段的返回值T,return Void;返回CompletableFuture<Void>

  • thenAccept
    该方法是同步的
public static void main(String[] args) {
        CompletableFuture<Void> stringCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "---------supplyAsync---------开始---");
            System.out.println(Thread.currentThread().getName() + "---------supplyAsync---------结束---");
            return "hello";
        }).thenAccept(s -> {
            System.out.println(Thread.currentThread().getName() + "---thenAcceptAsync---start---" + s);
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "---thenAcceptAsync----end---" + s);
        });
        try {
            System.out.println("============================");
            stringCompletableFuture.join();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

代码结果:这里写图片描述
thenAccept方法是mian线程执行的,阻塞了输出“============================”。

  • thenAcceptAsync
    以Async结尾代表是异步,将上述代码中thenAccept换成thenAcceptAsync,看输出结果:
    这里写图片描述

下面介绍的方法都会有以Async和没有Async结尾两种形式,都是类似的,以Async结尾代表异步,统一只介绍以Async结尾的方法。


thenRunAsync

Runnable 不接受上个阶段返回值和异常,return Void;返回CompletableFuture<Void>

public static void main(String[] args) {
        CompletableFuture<Void> voidCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "---------supplyAsync---------开始---");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "---------supplyAsync---------结束---");
            return "hello";
        }).thenRunAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "---thenRunAsync---start---");
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "---thenRunAsync----end---");
        });
        try {
            System.out.println(voidCompletableFuture.join());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

这里写图片描述


thenapplyAsync

Function<T, R>接收上个阶段的返回值T,return R ; 返回CompletableFuture<R>

public static void main(String[] args) {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            return "hello";
        }).thenApplyAsync(v -> {
            System.out.println(Thread.currentThread().getName() + "---thenApplyAsync---start---" + v);
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "---thenApplyAsync----end---" + v);
            return v.length();
        });
        try {
            System.out.println(completableFuture.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

这里写图片描述


whencompleteAsync

BiConsumer<T, U> 接收上个阶段的返回值T和异常U,return Void;返回上个阶段返回值CompletableFuture<T>

public static void main(String[] args) {
        CompletableFuture<String> stringCompletableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "---------supplyAsync-----------");
            return "hello";
        }).whenCompleteAsync((V, T) -> {
            System.out.println(Thread.currentThread().getName() + "---whenCompleteAsync---start---" + V);
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "---whenCompleteAsync----end---" + V);
        });
        try {
            System.out.println(stringCompletableFuture.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

这里写图片描述


handleAsync

BiFunction<T, U, R> 接收上个阶段的返回值T和异常U,return R;返回CompletableFuture<R>

public static void main(String[] args) {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName() + "---------supplyAsync---------开始---");
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "---------supplyAsync---------结束---");
            int e = 2/0;
            return "hello";
        }).handleAsync((s, v) -> {
            System.out.println(Thread.currentThread().getName() + "---handle---start---" + s);
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + "---handle----end---" + s);
            System.out.println("捕获的异常:"+ v);
            return s == null ? 0 : s.length();
        });
        try {
            System.out.println(completableFuture.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

这里写图片描述

### Java 多线程 CompletableFuture 使用教程 #### 1. 基本概念 `CompletableFuture` 是 Java 8 中引入的一种强大的异步编程工具,它不仅实现了 `Future` 接口还扩展了 `CompletionStage` 接口,从而提供了更丰富的异步任务管理能力[^3]。 #### 2. 创建异步任务 可以通过多种方式创建 `CompletableFuture` 实例: - **supplyAsync**: 返回带有计算结果的任务。 ```java CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> { return "Hello, world!"; }); ``` - **runAsync**: 执行不带返回值的任务 ```java CompletableFuture<Void> voidFuture = CompletableFuture.runAsync(() -> { System.out.println("Running asynchronously"); }); ``` 这两种方法都可以接受自定义的 `ExecutorService` 来指定任务执行所在的线程池[^1]。 #### 3. 组合多个异步任务 `CompletableFuture` 支持链式调用来组合多个阶段的操作,比如 `.thenApply()`、`.thenCompose()` `.thenCombine()` 方法可用于串联不同类型的后续动作。这使得编写复杂业务逻辑变得更为直观简洁[^4]。 例如,两个独立的异步请求完成后合并它们的结果: ```java CompletableFuture<Integer> cf1 = CompletableFuture.supplyAsync(() -> 1); CompletableFuture<Double> cf2 = CompletableFuture.supplyAsync(() -> 2.0); cf1.thenCombine(cf2, (i, d) -> i + d.intValue()).thenAccept(System.out::println); // 输出可能是:3 或者其它数值取决于浮点数转换行为 ``` #### 4. 非阻塞地获取结果 为了防止因长时间等待而导致应用程序卡死,在实际开发中应尽可能避免直接调用 `get()` 方法;而是推荐使用 `join()` 方法或设置合理的超时机制来安全地取得最终成果[^5]。 当确实需要同步获取数据时,建议像下面这样加上超时期限以确保不会无限期挂起: ```java try { String result = future.get(5, TimeUnit.SECONDS); // 设置最大等待时间为五秒 } catch (TimeoutException e) { // 超时处理... } ``` #### 5. 错误处理 对于可能出现失败的情况,可以利用异常传播特性来自动生成新的已完成状态为失败的新实例,也可以显式注册回调函数来进行定制化错误恢复策略。 ```java future.exceptionally(ex -> { ex.printStackTrace(); return null; }); ``` --- ### 应用场景 由于具备良好的灵活性易用性,`CompletableFuture` 特别适合应用于以下场合: - 并发加载资源(如数据库查询) - HTTP 请求聚合服务端点 - 流水线式的批处理作业 - GUI事件驱动框架中的后台任务调度 通过上述特性的有效运用,能够显著提升系统的吞吐量以及用户体验流畅度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值