Future和CompletableFuture的区别是什么?

1 Future和CompletableFuture的区别是什么?

1.1 功能范围差异

  • Future
    仅提供基础异步任务状态查询(isDone/isCancelled)和结果获取(get()方法),无法实现任务链式调用或组合,需手动处理阻塞逻辑。

  • CompletableFuture
    支持链式调用、组合任务(如thenApply、thenCombine等)和函数式编程,内置异常处理(exceptionally方法)与超时控制,可构建复杂异步流程。

1.2 阻塞与非阻塞特性

  • Future
    必须通过阻塞式get()方法等待结果返回,易造成线程资源浪费。

  • CompletableFuture
    提供join()非阻塞等待方法,支持回调机制(如whenComplete)自动触发后续操作,减少线程空转。

1.3 线程管理机制

  • Future
    依赖外部ExecutorService提交任务,需手动管理线程池资源。

  • CompletableFuture
    默认使用ForkJoinPool.commonPool(),支持自定义线程池,通过CAS无锁机制实现高效并发

1.4 异常处理方式

  • Future
    任务异常仅在调用get()时抛出ExecutionException,需手动捕获处理。

  • CompletableFuture
    通过exceptionally()方法捕获异常并返回默认值,支持异常传播到后续链式操作。

1.5 任务组合能力对比

  • Future
    多个任务需通过循环或手动协调实现组合,代码复杂度高。

  • CompletableFuture
    内置allOf/anyOf等多任务协调方法,支持结果聚合与依赖编排,实现"异步流水线处理。

1.6 总结‌

Future是基础异步模型,适合单一任务场景;CompletableFuture通过组合式编程和函数式特性,成为现代Java高并发编程的核心工具。

2 CompletableFuture详解

2.1 CompletableFuture 基础

什么是 CompletableFuture?
  • 定义:Java 8 引入的异步编程工具,支持非阻塞、链式调用和任务组合。
  • 特点:
    • 基于 Future 的扩展,提供更丰富的异步操作。
    • 支持函数式编程(如 Lambda 表达式)。
    • 可手动完成任务或设置异常。
核心方法分类
方法类型示例方法(有返回值/无返回值)用途
任务创建supplyAsync/runAsync启动异步任务
链式处理thenApply/thenAccept对结果进行转换或消费
任务组合thenCompose/thenCombine组合多个 CompletableFuture
异常处理exceptionally/handle处理异步任务中的异常
手动控制complete/completeExceptionally主动设置任务结果或异常
批量任务allOf/anyOf等待多个任务完成

2.2 核心方法详解

2.2.1 创建/获取结果和出发计算
创建

supplyAsync

  • 用途:提交有返回值的异步任务。
  • 参数:
    • Supplier<U>: 提供结果的函数。
    • Executor(可选):自定义线程池(默认使用 ForkJoinPool(守护线程、分治理念))。
  • 示例:
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // 模拟耗时操作
    return "Result";
});

runAsync

  • 用途:提交无返回值的异步任务(Runnable)。
  • 参数:
    • Runnable: 无返回值的任务。
    • Executor(可选):自定义线程池。
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    System.out.println("Task executed");
});
获取结果出发计算
public T get() // 死等
public T get(Long timeout, TimeUnit unit) // 超时抛出异常
public T join() // 不需要抛出异常
public T getNow(T valueIfAbsent) //如果没有计算完结果,则给默认值(立即获取结果不阻塞)
public boolean complete(T value) // 如果计算完成返回True,否则返回False
2.2.2 对结果进行处理/消费

thenApply
handlethenApply类似,

  • thenApply遇到异常直接中断,不执行回调,会中断。

  • handle可同时处理正常结果和异常,继续执行后续逻辑,不会中断。

  • 用途:对结果进行转换(类似 Stream.map)。任务A执行完执行BB需要A的结果,同时任务B有返回值。

  • 参数:Function<T, U>,接受输入 T,返回 U

  • 示例

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> "10")
    .thenApply(s -> Integer.parseInt(s)); // 转换为整数

thenAccept

  • 用途:消费结果(不返回新值)。任务A执行完执行BB需要A的结果,但是任务B无返回值。
  • 参数:Consumer<T>,接受输入 T,无返回值。
  • 示例
CompletableFuture.supplyAsync(() -> "Result")
    .thenAccept(s -> System.out.println("Received: " + s));

thenRun

  • 用途:在任务完成后执行操作(不访问结果)。任务A执行完执行B,并且B不需要A的结果。
  • 参数:Runnable。
  • 示例:
CompletableFuture.supplyAsync(() -> "Result")
    .thenRun(() -> System.out.println("Task finished"));
2.2.3 组合多个任务

thenCompose

  • 用途:将两个异步任务串联(前一个结果作为后一个任务的输入)。
  • 参数:Function<T, CompletableFuture<U>>
  • 示例:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> "10")
    .thenCompose(s -> CompletableFuture.supplyAsync(() -> Integer.parseInt(s)));

thenCombine

  • 用途:合并两个独立任务的结果。
  • 参数:
    CompletionStage<U>:另一个任务。
    BiFunction<T, U, V>:合并函数。
  • 示例
CompletableFuture<Integer> futureA = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> futureB = CompletableFuture.supplyAsync(() -> 20);

futureA.thenCombine(futureB, (a, b) -> a + b)
       .thenAccept(sum -> System.out.println("Sum: " + sum)); // 输出 30

allOf 和 anyOf

allOf:等待所有任务完成。

CompletableFuture<Integer> futureA = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> futureB = CompletableFuture.supplyAsync(() -> 20);
CompletableFuture<Void> all = CompletableFuture.allOf(futureA, futureB);
all.thenRun(() -> System.out.println("All tasks done"));
List<Object> list = Stream.of(futureA, futureB, futureC) // 获取所有的结果
        .map(CompletableFuture::join) // 直接获取结果,不抛受检异常,不会阻塞,因为 allOf 已确保完成
        .collect(Collectors.toList());

anyOf:等待任一任务完成。

CompletableFuture<Object> any = CompletableFuture.anyOf(futureA, futureB);
any.thenAccept(result -> System.out.println("First result: " + result));
2.2.4 异常处理

exceptionally

  • 用途:捕获异常并提供默认值。
  • 参数:Function<Throwable, T>,返回降级结果。
  • 示例:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
    if (error) throw new RuntimeException("Error");
    return 10;
}).exceptionally(ex -> {
    System.out.println("Error: " + ex.getMessage());
    return 0; // 返回默认值
});

handle

  • 用途:无论成功或失败,统一处理结果和异常。
  • 参数:BiFunction<T, Throwable, U>
  • 示例:
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 10)
    .handle((result, ex) -> {
        if (ex != null) return 0;
        return result * 2;
    });
2.2.5 手动控制任务

complete

  • 用途:手动设置任务结果(如果未完成)。
CompletableFuture<String> future = new CompletableFuture<>();
future.complete("Manual Result"); // 立即完成

completeExceptionally

  • 用途:手动设置任务异常。
future.completeExceptionally(new RuntimeException("Failed"));

3 高级操作(Java 9+)

orTimeout

  • 用途:设置任务超时时间,超时抛出 TimeoutException
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    Thread.sleep(2000);
    return "Result";
}).orTimeout(1, TimeUnit.SECONDS); // 1秒超时

completeOnTimeout

  • 用途:超时后提供默认值。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    Thread.sleep(2000);
    return "Result";
}).completeOnTimeout("Timeout", 1, TimeUnit.SECONDS);

4 最佳实践

  • 避免阻塞 get():尽量使用回调(如 thenAccept)替代 get()。
  • 合理使用线程池
// 自定义线程池(避免耗尽默认线程池资源)
ExecutorService executor = Executors.newFixedThreadPool(10);
CompletableFuture.supplyAsync(() -> task(), executor);
  • 避免回调地狱:通过链式调用拆分复杂逻辑。
  • 处理异常:始终使用 exceptionallyhandle 处理可能的异常。

5 完整示例

public class CompletableFutureDemo {
    public static void main(String[] args) throws Exception {
        // 创建异步任务
        CompletableFuture<Integer> futureA = CompletableFuture.supplyAsync(() -> 10);
        CompletableFuture<Integer> futureB = CompletableFuture.supplyAsync(() -> 20);

        // 合并结果并处理异常
        CompletableFuture<Integer> combined = futureA.thenCombine(futureB, (a, b) -> a + b)
                .exceptionally(ex -> {
                    System.out.println("Error: " + ex.getMessage());
                    return 0;
                });

        // 非阻塞获取结果
        combined.thenAccept(sum -> System.out.println("Sum: " + sum));

        // 阻塞等待任务完成(仅演示)
        combined.get();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逻辑峰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值