ExecutorService and thread pools
Stop creating threads by hand: submit tasks to a pool and shut it down properly.
Open this lesson in the learning hubKey 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 withawaitTermination.- Since Java 19
ExecutorServiceisAutoCloseable, so try-with-resources shuts down and waits for you. - An exception thrown inside
execute()disappears quietly. Catch and log in the task, or usesubmit()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.