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 sequentialloop
.
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