Reputation: 4217
Conceptually very simple. We have a huge legacy java site that uses NO threading / async. It takes forever to logon because it makes a dozen calls to different microservices, but all synchronously one at a time: each waits for the other to complete before making the next call. However NONE of the API calls depend on the result of any of the others.
But we do need to have all the results and combine them before we proceed. It seemed really obvious that we should be able to make these dozen calls in parallel, but wait for them ALL to complete to use their data IN THE VERY NEXT STEP.
So everything is synchronous before and after the calls. However it would be nice to send them each off on their own in parallel, asynchronously – or just in parallel – then we are only restricted by the single slowest call, not the total sequential times of all the calls.
I read Java 8 has this great new set of operations around CompletableFuture
. But I haven't found my use explained anywhere. We don't want the result to be a promise - we're happy to wait until they all complete and then continue. JS has Promise.all()
, but even that returns a promise.
All I can think of is to put a little wait look after the async calls are made, and only continue when we get all the results. Which is obviously nuts.
Am I missing something here? Because it seems so obvious to me, but no one else seems to have a problem with it – or else the approach is so simple no-one bothers to ask, and I'm just not getting it.
Upvotes: 10
Views: 8967
Reputation: 4496
If I understood it right, you want something like this:
ExecutorService executorService = Executors.newFixedThreadPool(4); // TODO: proper number of threads
Future<Integer> future1 = executorService.submit(() -> callService1()); // TODO: proper type and method
Future<String> future2 = executorService.submit(() -> callService2()); // TODO: proper type and method
executorService.shutdown();
executorService.awaitTermination(5, TimeUnit.MINUTES); // TODO: proper timeout
Integer result1 = future1.get(); // TODO: proper type
String result2 = future2.get(); // TODO: proper type
Explanation:
ExecutorService
with 4 threads, to which you can submit all your tasks (i.e. calls to microservices)ExecutorService.shutdown
(no more task submissions allowed) and ExecutorService.awaitTermination
(wait till all tasks are finished)Future.get
on all the futures to get the results
Future.get
will throw an ExecutionException
that wraps the exception thrown by the taskUpvotes: 8