Future和CompletableFuture的区别?原理全解与详细代码示例

在Java的并发编程中,想要优雅地处理多线程任务的结果,FutureCompletableFuture是最常见的选择。很多开发者只会基本用法,却对二者的原理与能力了解甚少,导致代码写起来繁琐,性能提升空间受限。那么,这两者究竟有何区别?各自适合哪些场景?本文将系统对比二者原理、功能异同,并配合实际代码实例,帮你真正掌握它们在现代Java开发中的用法精髓。


一、Future概述

1. 简介

Future接口是Java 5引入的,代表着一个异步任务执行后结果的“占位符”。你可以提交任务,稍后通过Future对象获取结果或监控状态。

2. 常见方法

  • get():阻塞等待任务完成并返回结果
  • get(timeout, unit):带超时时间的阻塞
  • cancel(boolean mayInterruptIfRunning):取消任务
  • isDone():判断是否已完成
  • isCancelled():判断是否已取消

3. 典型用法及代码

import java.util.concurrent.*;

public class FutureDemo {
    public static void main(String[] args) throws Exception {
        ExecutorService pool = Executors.newFixedThreadPool(2);
        Future<Integer> future = pool.submit(() -> {
            Thread.sleep(2000);
            return 42;
        });

        System.out.println("主线程继续干别的...");

        // 阻塞等待
        Integer result = future.get();
        System.out.println("异步计算结果:" + result);

        pool.shutdown();
    }
}
特点
  • 提交任务立即返回Future对象
  • 结果需要调用get()阻塞等待
  • 无法链式编排任务(不支持回调)
  • 不能直接组合多个任务

二、CompletableFuture概述

1. 简介

CompletableFuture是Java 8新增的异步任务增强API,是Future的升级版。它不仅实现了Future接口,还扩展了功能,支持丰富的异步编排、流式API、事件回调等。

2. 主要功能

  • 非阻塞回调:任务完成后直接触发回调,无需主动get阻塞
  • 链式编排:任务可“串行/并行”拼接组合
  • 异常处理:内建优雅的异常流转机制
  • 支持合并多个Future
  • 手动完成、自定义异步线程池

3. 常用静态工厂方法

  • runAsync(Runnable)/supplyAsync(Supplier):开启一个异步任务
  • thenApply:对结果进一步处理和转换
  • thenAccept:消费结果,无返回值
  • thenCombine/thenCompose:组合两个Future
  • handle/exceptionally:补救异常

4. 基本用法及代码

import java.util.concurrent.*;

public class CompletableFutureDemo {
    public static void main(String[] args) throws Exception {
        CompletableFuture<Integer> cf = CompletableFuture.supplyAsync(() -> {
            try { Thread.sleep(2000); } catch (InterruptedException e) {}
            return 42;
        });

        // 非阻塞式注册回调
        cf.thenAccept(result -> System.out.println("回调拿到结果:" + result));
        System.out.println("主线程继续执行...");

        Thread.sleep(2500); // 等辅助线程执行完
    }
}

三、Future与CompletableFuture的区别

特性FutureCompletableFuture
获取结果需get()阻塞可以同步get,也可异步回调(thenXXX)
任务编排不支持支持链式、组合、聚合
异常处理try-catch外显handle/exceptionally链式处理
取消任务支持支持
支持手动赋值不支持支持complete/completeExceptionally等
多任务聚合不友好allOf/anyOf直接组合
线程池需手动提交可指定池,也内置默认ForkJoin
主动完成不支持支持
JDK版本JDK5+JDK8+

四、实战对比与详细代码

1. Future获取异步结果(单一、阻塞方式)

ExecutorService pool = Executors.newCachedThreadPool();
Future<String> future = pool.submit(() -> {
    Thread.sleep(1000);
    return "Done";
});
String value = future.get(); // 阻塞
System.out.println(value);
pool.shutdown();

2. CompletableFuture 非阻塞回调(链式)

CompletableFuture<String> cf = CompletableFuture.supplyAsync(() -> {
    try {Thread.sleep(1000);} catch (InterruptedException ignored){}
    return "OK";
});
cf.thenApply(s -> s + " - 完成后加工")
  .thenAccept(System.out::println); // 非阻塞

Thread.sleep(1500);

3. CompletableFuture 组合多个任务(allOf、anyOf)

CompletableFuture<Integer> one = CompletableFuture.supplyAsync(() -> 1);
CompletableFuture<Integer> two = CompletableFuture.supplyAsync(() -> 2);

CompletableFuture<Void> all = CompletableFuture.allOf(one, two);
all.thenRun(() -> {
    try {
        int result = one.get() + two.get();
        System.out.println("总和:" + result);
    } catch (Exception e) {}
});

Thread.sleep(100);

4. CompletableFuture 异常处理

CompletableFuture<Integer> cf = CompletableFuture.supplyAsync(() -> {
    if (true) throw new RuntimeException("boom!");
    return 100;
}).exceptionally(ex -> {
    System.out.println("出异常:" + ex.getMessage());
    return -1;
});

System.out.println("最终结果:" + cf.get());

五、应用场景最佳实践

  • Future适用场景

    • 简单异步,偶尔要等待结果
    • 并发量不大,业务逻辑清晰
    • 硬性依赖结果后再后续处理(但只能同步阻塞等待)
  • CompletableFuture适用场景

    • 流式复杂任务编排、聚合
    • 高并发、异步化、非阻塞服务端开发(如异步微服务调用)
    • 多任务一起跑,快速返回或异常自动补偿
    • 回调式业务通知、事件驱动设计

六、总结

Future 和 CompletableFuture 都是Java异步编程的重要工具。Future简单但能力有限,逐渐成为“历史遗留”;CompletableFuture支持更丰富的异步、组合、异常链式处理,是现代异步任务与响应式编排的首选。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值