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