If we use an ExecutorCompletionService we can submit a series of tasks as Callables and get the result interacting with the CompletionService as a queue.
But there is also the invokeAll of ExecutorService that accepts a Collection of tasks and we get a list of Future to retrieve the results.
As far as I can tell, there is no benefit in using one or over the other (except that we avoid a for loop using an invokeAll that we would have to submit the tasks to the CompletionService) and essentially they are the same idea with a slight difference.
So why are there 2 different ways to submit a series of tasks? Am I correct that performance wise they are equivalent? Is there a case that one is more suitable than the other? I can’t think of one.
Using a
ExecutorCompletionService.poll/take, you are receiving theFutures as they finish, in completion order (more or less). UsingExecutorService.invokeAll, you do not have this power; you either block until are all completed, or you specify a timeout after which the incomplete are cancelled.Now, below I will demonstrate how
invokeAllworks:This produces the following output:
Using
CompletionService, we see a different output:This produces the following output:
Note the times are relative to program start, not the previous message.
Test out a working example on Replit.