· Non-blocking
· Ability to Programmatically completing a future
· Perform Error handling
· Ability to Chain several futures
· Ability to combine results of multiple futures (that run in parallel)
CompletableFuture : A Simplified Guide to
Async Programming | by Rahat Shaikh | The Startup | Medium
// Get Movies playing for the selected showtime (date and time)
CompletableFuture<List<Movie>>
getMovieList(String day){
return CompletableFuture.supplyAsync( ()-> {
List movieList = new ArrayList<Movie>();
//getMovieList from backend
return movieList;
});
}
// Select seats
for the movie
//ShowDetails includes movie selected, date and time of the movie, along with
seats selected for that show
CompletableFuture<ShowDetails>
selectSeats (ShowTime showTime) {
return CompletableFuture.supplyAsync(() -> {
ShowDetails showDetails = new ShowDetails();
showDetails.setSeats(selectSeatsForShow());
return showDetails;
});
}
//Customer selects a movie from the movie list
CompletableFuture<Movie>
selectMovie(List<Movie> movies){
//user selects movie
return CompletableFuture.supplyAsync(() -> {
movie = getCustomerSelectedMovie();
return movie;
});
}
//Calculate ticket price
CompletableFuture<TicketPrice> getTicketPrice
(ShowDetails showdetails){
return CompletableFuture.supplyAsync(() -> {
ticketPrice = getTotalTicketPrice();
return ticketPrice; //final price
});
}
// Apply promo code if available
ShowDetails applyPromoCode (ShowDetails showdetails,
String promoCode){
showdetails.setFinalDiscount(getDiscount(promoCode));
return showdetails;
}
Chaining multiple futures to book the Movie Show
public void bookMyShow(ShowDetails showDetails, String promoCode){
CompletableFuture result =
getMovieList(showDetails.getShowTime().getDay())
.thenCompose(movies -> selectMovie(movies))
.thenCompose(movie -> selectSeats(showDetails.getShowTime())
.thenApply(showDetails1 ->
applyPromoCode(showDetails1,promoCode))
.thenCompose(showDetails2 -> getTicketPrice(showDetails2)));
}
Asynchronous programming in Java with
CompletableFuture (linkedin.com)
The difference has to do with the Executor that is responsible for running the code. Each operator on CompletableFuture generally has 3 versions.
1. thenApply(fn) - runs fn on a thread defined by the CompleteableFuture on which it is called,
so you generally cannot know where this will be executed.
It might immediately execute if the result is already available.
2. thenApplyAsync(fn) - runs fn on a environment-defined executor regardless of circumstances. For CompletableFuture this will generally be ForkJoinPool.commonPool().
3. thenApplyAsync(fn,exec) - runs fn on exec.
In the end the result is the same, but the scheduling behavior depends on the choice of method.