直接使用 Spring @Async 与 CompleteableFuture 相比有什么优势?

What advantage is there to using Spring @Async vs. CompleteableFuture directly?

使用 Spring Async 与仅自行返回 CompletableFuture 相比有何优势?

您的应用程序由容器管理。由于不鼓励您自己生成 Thread,您可以让容器注入托管的 Executor.

@Service
class MyService {
  @Autowired
  private Executor executor;

  public CompletableFuture<?> compute() {
    return CompletableFuture.supplyAsync(() -> /* compute value */, executor);
  }
}

两者之间没有“vs.”——这些是互补技术:

  • CompletableFuture 提供了一种方便的方法来链接异步计算的不同阶段——比 Spring 的 ListenableFuture;
  • 更灵活
  • @Async 为您的执行程序提供标准 Spring 配置,方便管理您的后台任务和线程。

但两者可以结合使用 (since Spring 4.2)。假设你想把下面的方法变成一个后台任务返回一个 CompletableFuture:

public String compute() {
    // do something slow
    return "my result";
}

你必须做的事情:

  • 如果尚未完成:使用 @EnableAsyncExecutor bean
  • 配置您的应用程序
  • @Async
  • 注释方法
  • 将其结果包装到 CompletableFuture.completedFuture()
@Async
public CompletableFuture<String> computeAsync() {
    // do something slow - no change to this part
    // note: no need to wrap your code in a lambda/method reference,
    //       no need to bother about executor handling
    return CompletableFuture.completedFuture("my result");
}

如您所见,您不必费心将后台任务提交给执行程序:Spring 会为您处理。您只需将结果包装到一个完整的 CompletableFuture 中,以便签名与调用者期望的相匹配。

事实上,这相当于:

@Autowire
private Executor executor;

public CompletableFuture<String> computeAsync() {
    return CompletableFuture.supplyAsync(() -> {
        // do something slow
        return "my result";
    }, executor);
}

但它消除了需要:

  • 注入执行器
  • supplyAsync()调用中处理执行者
  • 将逻辑包装在 lambda 中(或将其提取到单独的方法中)