Reputation: 23
I have a scenario where in I have to issue two REST calls that return a value each based on the current system state, and based on those two values, have to trigger a final clean up task asynchronously - the flow of control being more like a 'Y' scenario . I have looked through the CompletableFuture interface, and is unable to find a way to accomplish this in a non-blocking fashion
I have tried this, and cant seem to find a way to get it working
// Verify task status
CompletableFuture<AuditResult> checkOneFuture =
CompletableFuture.supplyAsync(() -> dummyService.fetchSystemState(var1, var2),
executorService);
CompletableFuture<AuditResult> checkTwoFuture =
CompletableFuture.supplyAsync(() -> dummyService.fetchSystemState(var1, var3),
executorService);
CompletableFuture<CompletableFuture<Boolean>> cleanUpFuture =
checkOneFuture.thenCombineAsync(checkTwoFuture, (check1, check2) -> {
if (check1.getSuccess() && check2.getSuccess()){
CompletableFuture<Boolean> cleanUpFutuer = CompletableFuture.supplyAsync(() -> cleanUp(check1.id), executorService);
return syncFuture;
} else {
return CompletableFuture.completedFuture(false);
}
}, executorService);
cleanUpFuture.join();
The cleanUpFuture is obviously syntactically not correct, and I am trying to figure ways to get this scenario working. Please help
Upvotes: 0
Views: 1785
Reputation: 14999
As Slaw says in his comment, why not just return boolean
?
CompletableFuture<Boolean> cleanUpFuture =
checkOneFuture.thenCombineAsync(checkTwoFuture, (check1, check2) -> {
if (check1.getSuccess() && check2.getSuccess()) {
return cleanUp(check1.id); // will be scheduled due to combineAsync
} else {
return false;
}
}, executorService);
Note: for a shorter version, you can do
(check1, check2) -> check1.getSuccess() && check2.getSuccess() && cleanUp(check1.id);
Upvotes: 2
Reputation: 2294
You can acheive this by a ForkJoinPool
. Subdivizing your call in subtask by calling fork()
and reassemble the whole with a join()
For this you have maybe to implements a RecursiveTask
EDIT : Using CompletableFuture
If your purpose is to run two async processings in parallel and trigger another on completion of the later then allOf()
is the best method.
Here is an example :
public CompletableFuture<String> findSomeValue() {
return CompletableFuture.supplyAsync(() -> {
sleep(1);
return "Niraj";
});
}
@Test
public void completableFutureAllof() {
List<CompletableFuture<String>> list = new ArrayList<>();
IntStream.range(0, 5).forEach(num -> {
list.add(findSomeValue());
});
CompletableFuture<Void> allfuture = CompletableFuture.allOf(list.toArray(new CompletableFuture[list.size()]));//Created All of object
CompletableFuture<List<String>> allFutureList = allfuture.thenApply(val -> {
return list.stream().map(f -> f.join()).collect(Collectors.toList());
});
CompletableFuture<String> futureHavingAllValues = allFutureList.thenApply(fn -> {
System.out.println("I am here");
return fn.stream().collect(Collectors.joining());});
String concatenateString = futureHavingAllValues.join();
assertEquals("NirajNirajNirajNirajNiraj", concatenateString);
}
This is example and more explanations are provided in this article
Upvotes: 1