Thread Pools That Cause OOM: Pitfalls of FixedThreadPool & CachedThreadPool
The article explains how Java's Executors utility creates thread pools that can unintentionally exhaust memory, detailing why FixedThreadPool with an unbounded queue and CachedThreadPool with unlimited threads often lead to OutOfMemoryError, and provides code examples and analysis from Alibaba's Java Development Handbook.
Pooling techniques are often used to cache objects whose creation incurs high performance costs; a pool pre‑creates such objects and reuses them after they are returned.
Manual Thread‑Pool Declaration
Developers can manually declare a thread pool, as illustrated in the accompanying diagram.
Convenient Creation via Executors
The JDK provides the Executors utility class with many shortcut methods for quickly creating thread pools.
FixedThreadPool Can Trigger OOM
When a single‑thread FixedThreadPool is initialized and each submitted task creates a large string and then sleeps, the JVM soon throws an OutOfMemoryError (GC overhead limit exceeded). The stack trace is shown below:
Exception in thread "http-nio-45678-ClientPoller"
java.lang.OutOfMemoryError: GC overhead limit exceededThe underlying cause is that newFixedThreadPool builds its work queue as a LinkedBlockingQueue with the default capacity Integer.MAX_VALUE. This effectively creates an unbounded queue, which quickly fills up when tasks accumulate, exhausting heap memory.
Although newFixedThreadPool fixes the number of worker threads, the virtually unlimited task queue means that a large number of slow or memory‑intensive tasks can cause the JVM to run out of memory.
CachedThreadPool Can Also Lead to OOM
newCachedThreadPoolcreates a thread pool whose maximum thread count is Integer.MAX_VALUE and whose work queue is a SynchronousQueue (a queue with no storage capacity). Each incoming request must be handled by an existing idle thread; if none is available, a new thread is created.
In a scenario where each task runs for about an hour, a burst of incoming tasks results in the creation of a huge number of threads. Since each thread consumes stack memory (e.g., 1 MB), the unbounded growth inevitably triggers an OutOfMemoryError such as "unable to create new native thread".
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}Reference
The observations are documented in the "Alibaba Java Development Manual".
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
JavaEdge
First‑line development experience at multiple leading tech firms; now a software architect at a Shanghai state‑owned enterprise and founder of Programming Yanxuan. Nearly 300k followers online; expertise in distributed system design, AIGC application development, and quantitative finance investing.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
