Issue
I have Service.class with start()
method:
public void start() {
for (int i = 0; i < companiesList.size(); i++) {
asychronous.someAsynchronous(...);
}
log.info("Start method has finished");
}
I have Asynchronous.class with someAsynchronous()
method:
@Async("threadPoolTaskExecutor")
public CompletableFuture<Void> someAsynchronous(some_parameters) {
//do some stuff
return null;
}
The log.info()
shows up before someAsynchronous()
methods has finished.
How to force it to wait for log.info()
until someSynchronous()
methods in loop will finish? Btw: Asynchronous threads are still running after finishing loop.
Solution
The CompletableFuture<Void>
calls are requested to be executed but after all of them start in separate threads, the for-loop finishes and the log is printed even before any of them finished. This is the advantage of the asynchronous processing - you don't care about their results and how much time they took to execute.
To achieve you want, you have to periodically check whether all of them are finished before you proceed to the log outoput.
// Adds executions to the List
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (int i = 0; i < companiesList.size(); i++) {
futures.add(asychronous.someAsynchronous(...));
}
// Periodical check
Iterator<CompletableFuture<Void>> iterator = futures.iterator();
while (iterator.hasNext()) {
CompletableFuture<Void> future = iterator.next(); // get the next one
if (future.isDone()) { // if finished...
//... // ... do an action
iterator.remove(); // ... and remove from the Iterator
}
if (!iterator.hasNext()) { // if you reach the end
iterator = futures.iterator(); // ... repeat the remaining Futures
}
}
log.info("Start method has finished");
Note this method doesn't finish until all of the executions are done.
Edit: Thanks to @Kayaman who suggested using a single method dedicated for that replacing the whole Iterator
logics. The futures
must be an array:
// Adds executions to the List
List<CompletableFuture<Void>> futures = new ArrayList<>();
for (int i = 0; i < companiesList.size(); i++) {
futures.add(asychronous.someAsynchronous(...));
}
// Join the completion of all the threads
CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join();
log.info("Start method has finished");
Answered By - Nikolas Charalambidis
Answer Checked By - Katrina (JavaFixing Volunteer)