javaconcurrencyexecutorservicejava.util.concurrent

Whether to use invokeAll or submit - java Executor service


I have a scenario where I have to execute 5 thread asynchronously for the same callable. As far as I understand, there are two options:

1) using submit(Callable)

ExecutorService executorService = Executors.newFixedThreadPool(5);
List<Future<String>> futures = new ArrayList<>();
for(Callable callableItem: myCallableList){
    futures.add(executorService.submit(callableItem));
}

2) using invokeAll(Collections of Callable)

ExecutorService executorService = Executors.newFixedThreadPool(5);
List<Future<String>> futures = executorService.invokeAll(myCallableList));
  1. What should be the preferred way?
  2. Is there any disadvantage or performance impact in any of them compared to the other one?

Solution

  • Depending on application requirement, either of them is preferred.

    Option 1 : You are submitting the tasks to ExecutorService and you are not waiting for the completion of all tasks, which have been submitted to ExecutorService

    Use case: If you don't want to wait after task submit() to ExecutorService, prefer Option 1.

    Majorly it is used for Asynchronous request submission. For non-critical use cases, I will prefer the option

    Example : Assume that you have booked a ticket ( say flight ticket). You want to log the request and response for housekeeping. The logging may be in a file OR database. In this use case, logging is not critical to send payment response to user. Submit the logging request to ExecutorService and that activity is handled asynchronously.

    Option 2 : You are waiting for completion of all tasks, which have been submitted to ExecutorService.

    Example: Assume that you have developed a multi player game. 10 players are part of the game. 5 players lost their money. Before start of the next game, you have given option for these 5 players to re-fill their balances. Now for starting next game, you have to wait for the result of all players re-fill requests. Then only you can start next game.

    Is there any disadvantage or performance impact in any of them compared to the other one?

    It depends on business use case as explained above. Both have their advantages / dis-advantages.

    And one more important thing: Whatever option you prefer, FutureTask swallows Exceptions during task execution. You have to be careful. Have a look at this SE question: Handling Exceptions for ThreadPoolExecutor

    With Java 8, you have one more option: ExecutorCompletionService

    A CompletionService that uses a supplied Executor to execute tasks. This class arranges that submitted tasks are, upon completion, placed on a queue accessible using take. The class is lightweight enough to be suitable for transient use when processing groups of tasks.

    Have a look at related SE question: ExecutorCompletionService? Why do need one if we have invokeAll?