Reputation: 5648
What's the advantage of using Spring Async vs. Just returning the CompletableFuture
on your own?
Upvotes: 45
Views: 30242
Reputation: 29
@Async
is more save in a Spring App. Using CompletableFuture
in a Spring Application can be dangerous. The Threads are not created by Spring and do not inherit from Spring own configured ClassLoader
. This way, dynamic loading of classes can fail at runtime inside a CompletableFuture
execution block. See CompletableFuture / ForkJoinPool Set Class Loader.
Upvotes: 3
Reputation: 20560
There is no “vs.” between the two – these are complementary technologies:
CompletableFuture
provides a convenient way to chain different stages of asynchronous computation – with more flexibility than Spring's ListenableFuture
;@Async
provides convenient management of your background tasks and threads, with standard Spring configuration for your executor(s).But both can be combined (since Spring 4.2). Suppose you want to turn the following method into a background task returning a CompletableFuture
:
public String compute() {
// do something slow
return "my result";
}
What you have to do:
@EnableAsync
and an 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");
}
As you notice, you don't have to bother about submitting the background task to an executor: Spring takes care of that for you. You only have to wrap the result into into a completed CompletableFuture
so that the signature matches what the caller expects.
In fact, this is equivalent to:
@Autowire
private Executor executor;
public CompletableFuture<String> computeAsync() {
return CompletableFuture.supplyAsync(() -> {
// do something slow
return "my result";
}, executor);
}
but it removes the need to:
supplyAsync()
callUpvotes: 44
Reputation: 11740
Your application is managed by the container. Since it's discouraged to spawn Thread
s on you own, you can let the container inject a managed Executor
.
@Service
class MyService {
@Autowired
private Executor executor;
public CompletableFuture<?> compute() {
return CompletableFuture.supplyAsync(() -> /* compute value */, executor);
}
}
Upvotes: 25