使用 Spring Async 与仅返回
CompletableFuture
相比有什么优势?
两者之间不存在“vs.”——这些是互补技术:
CompletableFuture
提供了一种便捷的方法来链接异步计算的不同阶段 - 比 Spring 的 ListenableFuture
;@Async
为您的执行器提供标准 Spring 配置,方便管理后台任务和线程。但两者可以结合起来(自 Spring 4.2)。假设您想将以下方法变成返回
CompletableFuture
的后台任务:
public String compute() {
// do something slow
return "my result";
}
你必须做什么:
@EnableAsync
和 Executor
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()
通话中与执行者打交道您的应用程序由容器管理。由于不鼓励您自己生成
Thread
,因此您可以让容器注入托管 Executor
。
@Service
class MyService {
@Autowired
private Executor executor;
public CompletableFuture<?> compute() {
return CompletableFuture.supplyAsync(() -> /* compute value */, executor);
}
}
@Async
在Spring应用程序中更节省。在 Spring 应用程序中使用 CompletableFuture
可能很危险。线程不是由 Spring 创建的,也不是继承自 Spring 自己配置的 ClassLoader
。这样,类的动态加载可能会在运行时在 CompletableFuture
执行块内失败。请参阅 CompletableFuture / ForkJoinPool 设置类加载器。