Someone on the channel today asked about how to run a series of tasks, with a terminal condition of sorts. Basically, they wanted to run a number of tasks, and know when they were done.

The question was originally built around having a List of results ( List<integer> , maybe?), counting the number of results until the number of results matched the number of tasks.

The channel suggested using an ExecutorService , particularly the shutdown() and awaitTermination() methods, with another suggestion being invokeAll() – which seemed particularly apt because the person asking didn’t want to have to build a new ExecutorService over and over again (which the shutdown() call would necessitate, although the cost of doing this shouldn’t be very high.)

Here’s an example with Java 8, of using the invokeAll() to execute a series of tasks; the task is made-up (it basically rolls three six-sided dice to determine a histogram of results, as a callback to Dungeons and Dragons). It has one dependency, on Apache’s commons-lang3.

package org.javachannel.examples.executors; import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.LockSupport; import java.util.stream.IntStream; class Worker implements Callable { int roll() { LockSupport.parkNanos((long) (Math.random() * 10000000)); return (int) (Math.random() * 6) + 1; } @Override public Integer call() throws Exception { return roll() + roll() + roll(); } } public class Main { public static void main(String[] args) throws InterruptedException { List workerList = new ArrayList<>(); IntStream.range(0, 100000).forEach(i -> workerList.add(new Worker())); ExecutorService service = Executors.newCachedThreadPool(); int[] count = new int[19]; service.invokeAll(workerList).stream().map(f -> { try { return f.get(); } catch (Throwable e) { return 0; } }).forEach(m -> count[m]++); IntStream.rangeClosed(3, 18).forEach(r -> { System.out.printf("%02d %s%n", r, StringUtils.repeat("*", count[r]/100)); }); } }