How to deadlock a Java ExecutorService
The article explains how an ExecutorService in Java can deadlock when a task submitted to a single-threaded executor waits for another task that is queued behind it, causing the thread to be blocked indefinitely and preventing the second task from ever running.
Background
- Java's ExecutorService is a framework for running tasks concurrently (in parallel) using a pool of reusable threads. Developers submit tasks to it instead of manually creating threads.
- A "thread pool" with a fixed number of threads (e.g., 2 threads) can only run that many tasks at once. Extra tasks wait in a queue.
- This article shows a subtle deadlock bug: if a task running in the pool submits another task to the same pool and then waits for its result (via Future.get()), it can hang forever — the waiting task occupies one thread, but the subtask needs a thread from the same pool. If all threads are occupied waiting, no thread remains to run the subtask, so nothing progresses.
- This is a well-known trap called "thread starvation deadlock" or "ExecutorService deadlock". It's a common interview question and a real bug in production code.