Difference between Executor and ExecutorCompletionservice in java

Suppose you had a set of tasks A, B, C, D, E and you want to execute each of them asynchronously in an Executor and process the results 1 by 1 as they complete.

With an Executor, you would do so like this:

List<Future<?>> futures = new ArrayList<Future<?>>();
futures.add(executorService.submit(A));
futures.add(executorService.submit(B));
futures.add(executorService.submit(C));
futures.add(executorService.submit(D));
futures.add(executorService.submit(E));

//This loop must process the tasks in the order they were submitted: A, B, C, D, E
for (Future<?> future:futures) {
    ? result = future.get();
    // Some processing here
}

The problem with this method is that there is no guarantee that task A will complete first. Thus, it is possible that the main thread will be blocking idly waiting for task A to complete when it could be processing the result of another task (say task B). Result processing latency could be reduced by using an ExecutorCompletionService.

List<Future<?>> futures = new ArrayList<Future<?>>();
futures.add(executorCompletionService.submit(A));
futures.add(executorCompletionService.submit(B));
futures.add(executorCompletionService.submit(C));
futures.add(executorCompletionService.submit(D));
futures.add(executorCompletionService.submit(E));

//This for loop will process the tasks in the order they are completed,  
//regardless of submission order
for (int i=0; i<futures.size(); i++) {
    ? result = executorCompletionService.take().get();
    // Some processing here
}

So, in essence, ExecutorCompletionService could be used to squeeze out a little more efficiency when the order of processing task results does not matter.

One important thing to note though. The implementation of ExecutorCompletionService contains a queue of results. If take or poll are not called to drain that queue, a memory leak will occur. Some people use the Future returned by submit to process results and this is NOT correct usage.


An ExecutorCompletionService will simply wrap and delegate to a normal Executor and offer convenience methods for retrieving the most recently completed tasks.

The api has a few examples that should get you going

http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorCompletionService.html