Java 直接使用Spring@Async与CompletableFuture相比有什么优势?
使用与仅返回Java 直接使用Spring@Async与CompletableFuture相比有什么优势?,java,spring,asynchronous,java-8,completable-future,Java,Spring,Asynchronous,Java 8,Completable Future,使用与仅返回CompletableFuture的优点是什么 您的应用程序由容器管理。由于不鼓励自己生成线程s,因此可以让容器注入托管执行器 @Service class MyService { @Autowired private Executor executor; public CompletableFuture<?> compute() { return CompletableFuture.supplyAsync(() -> /* compute v
CompletableFuture
的优点是什么 您的应用程序由容器管理。由于不鼓励自己生成线程
s,因此可以让容器注入托管执行器
@Service
class MyService {
@Autowired
private Executor executor;
public CompletableFuture<?> compute() {
return CompletableFuture.supplyAsync(() -> /* compute value */, executor);
}
}
@服务
类MyService{
@自动连线
私人遗嘱执行人;
公共CompletableFuture compute(){
返回CompletableFuture.SupplySync(()->/*计算值*/,执行器);
}
}
两者之间没有“对”:它们是互补的技术:
提供了一种方便的方式来链接异步计算的不同阶段,比Spring的CompletableFuture
更具灵活性李>ListenableFuture
为您的后台任务和线程提供方便的管理,并为您的执行器提供标准的Spring配置@Async
CompletableFuture
:
public String compute() {
// do something slow
return "my result";
}
你必须做的是:
- 如果尚未完成:使用
和@EnableAsync
bean配置应用程序执行器
- 用
@Async
- 将其结果包装到
CompletableFuture.completedFuture()
@Async
公共CompletableFuture computeAsync(){
//做点慢动作-不要改变这部分
//注意:无需将代码包装在lambda/方法引用中,
//不必为遗嘱执行人的处理而烦恼
返回CompletableFuture.completedFuture(“我的结果”);
}
正如您所注意到的,您不必费心将后台任务提交给执行者:Spring会为您处理这些。您只需将结果包装成一个已完成的
CompletableFuture
,以便签名符合调用方的期望。可能会对您有所帮助。这在java 8之前的版本中可能是有意义的。但是CompletableFuture在默认情况下会分叉到分叉连接池中。您拥有一个托管环境。不鼓励您自己生成线程,但如果必须这样做,那么您可以将CompletableFuture
与注入的ExecutorService
一起使用,该服务应由您的容器管理。将其作为一个答案提供,如果您获得了支持,我们就来看看。我不认为这是一种比公认答案中的更好的方法。那里没有那么神奇。我遗漏了什么?@BalázsNémeth,不确定你正在用“那里的魔法更少”重新填充哪一个,但我认为它是公认答案中的一个。事实上,如果你不喜欢魔术,像往常一样,编程版本会更适合你。然而,人们通常认为声明性编程更好,这是使用Spring的代码> @ AsYNC/<代码>时的情况。当然,这需要一些“魔法”;)我明白你的意思@异步是一个更高级别的概念。我可能应该相信它,但我不知何故不相信:)@BalázsNémeth我特别欣赏@Async
的一点是,您不必指定执行器,但仍然可以通过Spring的@enablesync
配置对其进行自定义。使用supplyAsync()
,要么使用公共F-J池(可能不需要),要么每次使用时都必须传递executor参数。
@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");
}