Skip to content

CompletableFuture、Future、FutureTask


Future

一、是什么?
Future 是 Java 5 引入的接口(java.util.concurrent.Future),代表一个异步计算的结果。它提供了一种检查计算是否完成、等待计算完成以及获取计算结果的方法。

二、解决什么问题

  1. 阻塞问题:传统同步代码会阻塞主线程等待耗时操作(如网络请求、数据库查询)。
  2. 结果获取:需要一种机制在耗时操作完成后获取结果,而不阻塞主线程。
  3. 任务状态跟踪:需要监控异步任务的状态(是否完成、是否取消)。

三、核心方法

java
boolean isDone();         // 检查任务是否完成
V get() throws ...;      // 阻塞获取结果(直到完成)
V get(long timeout, TimeUnit unit) throws ...; // 限时阻塞获取
boolean cancel(boolean mayInterrupt); // 尝试取消任务

四、应用场景

  • 提交任务到线程池后获取结果
  • 并行执行多个独立任务(每个任务一个 Future)
  • 设置任务超时时间(避免无限等待)

五、重要注意事项

  1. get() 方法会阻塞调用线程,可能影响性能。
  2. 无法手动设置结果或组合多个任务(如“任务 A 完成后触发任务 B”)。
  3. 异常处理需在任务内部捕获,无法通过 Future 链式处理。

FutureTask

一、是什么?
FutureTask 是 Future 接口的**基础实现类**(java.util.concurrent.FutureTask),同时实现了 Runnable接口。它既可作为Future使用,也可作为Runnable` 提交给线程执行。

二、解决什么问题

  1. 统一任务封装:将 Callable/Runnable 任务封装成 Runnable + Future 的结合体。
  2. 直接线程执行:可直接被 Thread 或线程池执行(因实现了 Runnable)。
  3. 复用任务对象:同一个任务可被多次执行(需手动重置状态)。

三、核心方法

java
FutureTask(Callable<V> callable); // 构造方法(接受Callable)
FutureTask(Runnable runnable, V result); // 构造方法(接受Runnable)

四、应用场景

  • 需要手动创建任务并交给线程执行(而非线程池)
  • 将已有 CallableRunnable 包装成 Future
  • 需要复用任务对象(通过重置状态)

五、重要注意事项

  1. 任务一旦完成,状态不可重置(除非调用 runAndReset())。
  2. Future 一样,get() 会阻塞线程。
  3. 无法组合多个任务或链式处理结果。

CompletableFuture

一、是什么?
CompletableFuture 是 Java 8 引入的类(java.util.concurrent.CompletableFuture),实现了 Future 接口。它支持非阻塞编程链式调用组合异步任务,是函数式异步编程的核心工具。

二、解决什么问题

  1. 阻塞获取结果:通过回调(如 thenApply())避免 get() 阻塞。
  2. 任务组合:轻松实现“任务 A 完成后触发任务 B”或“所有任务完成后合并结果”。
  3. 异常处理:链式处理异常(exceptionally()/handle())。
  4. 手动控制结果:可主动完成任务(complete()/completeExceptionally())。

三、核心方法

java
static CompletableFuture<Void> runAsync(Runnable runnable); // 无返回任务
static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier); // 有返回任务

// 链式处理
thenApply(Function)    // 转换结果
thenAccept(Consumer)   // 消费结果
thenRun(Runnable)      // 无结果操作

// 组合任务
thenCompose()          // 串行组合(A 完成后触发 B)
thenCombine()          // 并行组合(A+B 完成后合并结果)
allOf() / anyOf()      // 聚合多个任务

// 异常处理
exceptionally()        // 捕获异常并返回默认值
handle()               // 无论成功/异常都处理

四、应用场景

  • 异步流水线处理(如:请求 API → 解析数据 → 保存数据库)
  • 合并多个独立异步任务的结果(如:并发查询多个服务)
  • 实现超时控制(orTimeout()
  • 响应式编程(如结合 Spring WebFlux)

五、Java 示例

java
CompletableFuture.supplyAsync(() -> fetchUserFromDB(userId)) // 异步查询
    .thenApply(user -> enrichUser(user))      // 转换结果
    .thenAccept(user -> saveToCache(user))    // 消费结果
    .exceptionally(ex -> {                    // 异常处理
        log.error("Failed", ex);
        return null;
    })

六、重要注意事项

  1. 默认使用 ForkJoinPool.commonPool(),可指定自定义线程池避免资源竞争。
  2. 避免在回调中阻塞(如调用 get()),否则失去非阻塞优势。
  3. 合理处理异常,避免静默失败。

三者核心区别

特性FutureTaskCompletableFuture
是否阻塞是(get() 阻塞)否(支持回调)
任务组合能力✅(thenCompose/allOf 等)
手动设置结果✅(complete()
异常处理需在任务内部处理需在任务内部处理✅(链式处理)
函数式支持✅(Lambda/方法引用)
Java 版本5+5+8+

总结

  1. Future:基础接口,适用于简单异步任务获取结果,但需阻塞等待。
  2. FutureTaskFuture 的基础实现,可包装任务并直接交给线程执行。
  3. CompletableFuture现代异步编程首选,支持非阻塞、链式调用和任务组合,能优雅处理复杂异步流程。

建议

  • 简单场景用 Future + 线程池。
  • 复杂异步流水线、任务组合用 CompletableFuture
  • 除非特殊需求(如自定义任务状态),否则无需直接使用 FutureTask