Card 07/ 09

GotchaDifficulty: Advanced1 min

Why Your Program Hung After main Returned

The batch job finishes, logs its summary, and the process never exits. Every task completed, and the container has to be killed.

java
ExecutorService pool = Executors.newFixedThreadPool(4);

for (Path file : files) { pool.submit(() -> process(file)); }

System.out.println("done");

A pool's threads are non-daemon by default and they do not stop when their queue empties — they wait for more work. The virtual machine exits when the last non-daemon thread finishes, and four of them are waiting patiently forever.

Two fixes, and the second is the one to reach for in new code.

java
pool.shutdown();
pool.awaitTermination(1, TimeUnit.MINUTES);

// or, since Java 19
try (ExecutorService pool = Executors.newFixedThreadPool(4)) {
    for (Path file : files) { pool.submit(() -> process(file)); }
}

The try-with-resources form calls shutdown and then waits, so leaving the block means every task has finished. Whichever you use, a pool that nothing shuts down is a process that nothing can stop.