Encodera

Thanks for reading!

Donate to the site — we work hard for you.

How to run tasks in parallel

Short answer

An ExecutorService is a thread pool you hand tasks to. submit() returns a Future — a "promise" of a result — and get() waits for it:

int slowSquare(int n) throws InterruptedException {
    Thread.sleep(200);
    return n * n;
}
 
void main() throws Exception {
    try (ExecutorService pool = Executors.newFixedThreadPool(3)) {
        Future<Integer> a = pool.submit(() -> slowSquare(2));
        Future<Integer> b = pool.submit(() -> slowSquare(3));
        Future<Integer> c = pool.submit(() -> slowSquare(4));
 
        IO.println(a.get() + b.get() + c.get());
    }
}

Output:

29

The three 200 ms tasks run at the same time, so the program waits about 200 ms, not 600. Since Java 19 an ExecutorService can be closed with try-with-resources: it waits for the tasks and stops the threads.

A list of tasks

invokeAll() starts all tasks and returns a list of Futures in the same order:

void main() throws Exception {
    List<Callable<String>> tasks = List.of(
            () -> "report A",
            () -> "report B",
            () -> "report C");
 
    try (var pool = Executors.newFixedThreadPool(2)) {
        for (Future<String> future : pool.invokeAll(tasks)) {
            IO.println(future.get());
        }
    }
}

Output:

report A
report B
report C

An error in a task

An exception from a task is not lost: get() throws an ExecutionException, and the original exception is in getCause():

void main() throws InterruptedException {
    try (var pool = Executors.newSingleThreadExecutor()) {
        Future<Integer> future = pool.submit(() -> Integer.parseInt("oops"));
        try {
            future.get();
        } catch (ExecutionException e) {
            IO.println("Task failed: " + e.getCause().getMessage());
        }
    }
}

Output:

Task failed: For input string: "oops"

Common mistake

Calling get() right after each submit(). The program waits for the first task before sending the second, and nothing runs in parallel. Submit all the tasks first, then collect the results.

Functions used in this recipe

Thanks for reading!

Donate to the site — we work hard for you.