ExecutorService and thread pools

Multithreading · lesson 9 of 38 · 4 min read

Stop creating threads by hand: submit tasks to a pool and shut it down properly.

Open this lesson in the learning hub

Key points

  • A pool reuses a fixed set of threads. You submit tasks and the pool decides who runs them and when.
  • newFixedThreadPool(n) for steady load, newCachedThreadPool() for short bursts, newSingleThreadExecutor() to force work into order.
  • Size CPU-bound pools near the core count. I/O-bound pools need to be much larger, or use virtual threads instead.
  • shutdown() drains the queue, shutdownNow() interrupts running tasks. Neither one blocks, so follow with awaitTermination.
  • Since Java 19 ExecutorService is AutoCloseable, so try-with-resources shuts down and waits for you.
  • An exception thrown inside execute() disappears quietly. Catch and log in the task, or use submit() and check the Future.

Example

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class Main {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService pool = Executors.newFixedThreadPool(3);   // 3 threads, 6 jobs
        try {
            for (int i = 1; i <= 6; i++) {
                int job = i;
                pool.execute(() -> {
                    System.out.println("job " + job + " ran on " + Thread.currentThread().getName());
                    sleep(100);
                });
            }
        } finally {
            pool.shutdown();                                      // stop accepting, drain the queue
            boolean clean = pool.awaitTermination(5, TimeUnit.SECONDS);
            System.out.println("all jobs finished: " + clean);
        }
    }

    static void sleep(long ms) {
        try { Thread.sleep(ms); } catch (InterruptedException e) { Thread.currentThread().interrupt(); }
    }
}

Create pools, not threads, and always shut them down.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Multithreading course, and every lesson in it is listed on the Multithreading contents page.