【问题标题】:What advantage is there to using Spring @Async vs. CompleteableFuture directly?直接使用 Spring @Async 与 CompleteableFuture 有什么优势?
【发布时间】:2017-11-24 21:27:42
【问题描述】:

使用Spring Async 与仅返回CompletableFuture 相比有什么优势?

【问题讨论】:

  • 也许THIS 会帮助你。
  • 这在 pre java 8 中可能有意义。但 CompletableFuture 默认情况下会分叉到分叉连接池。
  • 您拥有一个托管环境。不鼓励自己生成线程,但如果必须这样做,您可以使用 CompletableFuture 和注入的 ExecutorService,它应该由您的容器管理。
  • 提供它作为答案,如果你得到了投票,我们就来吧。

标签: java spring asynchronous java-8 completable-future


【解决方案1】:

两者之间没有“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");
}

正如您所注意到的,您不必费心将后台任务提交给执行程序:S​​pring 会为您处理好这些。您只需要将结果包装到完整的CompletableFuture 中,以便签名与调用者的期望相匹配。

其实这相当于:

@Autowire
private Executor executor;

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

但它不需要:

  • 注入执行器
  • supplyAsync() 电话中与执行者打交道
  • 将逻辑包装在 lambda 中(或将其提取到单独的方法中)

【讨论】:

  • 我看不出这比已接受答案中的方法更好。那里的魔法更少。我错过了什么?
  • @BalázsNémeth,不确定您要使用“那里的魔法较少”重新推荐哪个,但我认为它是已接受答案中的那个。事实上,如果您不喜欢 magic,那么像往常一样,程序化版本会更适合您。然而,人们通常认为声明式编程更好,使用 Spring 的@Async 时就是这种情况。当然,这涉及到一些“magic” ;)
  • @BalázsNémeth 我特别欣赏@Async 的一件事是您不必指定执行程序,但您仍然可以通过Spring 的@EnableAsync 配置对其进行自定义。使用supplyAsync(),要么使用普通的 F-J 池(可能不可取),要么每次使用时都必须传递 executor 参数。
  • @privalou supplyAsync() 将安排您的供应商执行并使其在单独的线程上运行,这将是无用的,因为实际上没有什么要计算的。事实上completedFuture() 是非异步的等价物,它只是一种将值包装在CompletableFuture 中的便捷方式。 @Async 让 Spring 为您处理整个异步逻辑。如果您不使用@Async,我已在答案中添加等效代码,希望对您有所帮助。
  • @DidierL:这是否意味着,spring @Async 覆盖了 Java8 的 completedFuture 的行为,其目的是返回已计算结果的 CompletableFuture&lt;T&gt;。那么,Spring 的 @Async 将解析代码 sn-p 即“我的结果”并将其传递给 supplyAysnc() lambda?如果是,为什么在已经计算结果时将其传递给线程。如果我错了,请在这里澄清并纠正我
【解决方案2】:

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

@Service
class MyService {
  @Autowired
  private Executor executor;

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

【讨论】:

    猜你喜欢
    • 2012-05-02
    • 1970-01-01
    • 1970-01-01
    • 2012-11-30
    • 2010-09-17
    • 1970-01-01
    • 1970-01-01
    • 2010-09-24
    • 2010-12-27
    相关资源
    最近更新 更多