Playing with Java Executor - Tasks ExecutorService Parallel Loop

If the iterations of the loop are independent and we don’t need to wait for all tasks to complete before proceeding, we can use an Executor to transform a sequential loop into a parallel tasks execution.

Transform sequential loop into a parallel using ExecutorService and CompletionService

First consider an example which process all task using sequential loop.

Public void SequentialLoop(List elements) {
  for (Element e : elements)
      process(e);
}

Let's modify our code and use an ExecutorService to execute task in parallel.
public void processLoopInParallel(Executor exec, List elements) {
  for (final Element e : elements)
      exec.execute(new Runnable() {
          public void run() { process(e); }
      });
}

The second loop will return more quickly, since all the task are queued to the Executor, rather than waiting for each tasks to complete.

If you want to submit a set of tasks and you want to retrieve the results as they become available, we can use CompletionService

void solve(Executor e, Collection<callable<result>> solvers)
     throws InterruptedException, ExecutionException {
       CompletionService<result> ecs
           = new ExecutorCompletionService<result>(e);
       for (Callable<result> s : solvers)
           ecs.submit(s);
       //retrieve completed task results and use them  
       int n = solvers.size();
       for (int i = 0; i < n; ++i) {
           Result r = ecs.take().get();
           if (r != null)
               use(r);
       }
   }

The advantage of using CompletionService is that it always returns the first completed task result. In this way, we can ensure that we are not waiting for tasks to complete while uncompleted tasks are running in the background.

If you want to submit a set of tasks and wait for them all to complete, you can use ExecutorService.invokeAll