ExecutorService Shutdown & Rejection — Interview Questions
Reviewed by Gurusankar M.
Short Answer
Shut down gracefully with shutdown() (stop accepting new tasks, finish queued ones) then awaitTermination() with a timeout, falling back to shutdownNow() (interrupt running tasks, drain the queue) if it overruns. For overload, use a bounded queue plus a RejectedExecutionHandler — CallerRunsPolicy applies natural back-pressure by running the task on the submitting thread, while AbortPolicy (default) throws. Size the pool from the workload: CPU-bound ≈ cores; I/O-bound higher.
On this page
Concept Made Simple
Coffee Chat Question
“How do you shut down an ExecutorService cleanly and handle rejected tasks?”
Remember It Faster
Mind Map Answer
- shutdown()
- No new tasks; finish queued work
- shutdownNow()
- Interrupt running, return pending tasks
- awaitTermination
- Block up to a timeout for completion
- RejectedExecutionHandler
- Policy when the queue is full
The safe shutdown idiom: shutdown() → awaitTermination(timeout) → if still running, shutdownNow() → await again. Skipping this leaks threads and can hang JVM exit (non-daemon pool threads keep the process alive).
A bounded queue + CallerRunsPolicy gives back-pressure: when the pool and queue are full, the caller runs the task itself, naturally slowing intake instead of exploding memory with an unbounded queue.
Key takeaway: always own the pool's lifecycle and its overflow policy. Unbounded queues hide overload until OOM; a bounded queue with a rejection policy fails loudly and safely.
Learn by Doing
Hands-on Keyboard
ExecutorService pool = new ThreadPoolExecutor(
4, 8, 60, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(100), // bounded → back-pressure
new ThreadPoolExecutor.CallerRunsPolicy()); // rejection policy
// Graceful shutdown
pool.shutdown(); // stop accepting
if (!pool.awaitTermination(30, TimeUnit.SECONDS)) {
pool.shutdownNow(); // force-interrupt
}Think Beyond the Expected
What If?
Why can Executors.newFixedThreadPool() silently cause an OutOfMemoryError under load?
Because its factory uses an UNBOUNDED LinkedBlockingQueue. When tasks arrive faster than the fixed threads can process them, they pile up in that queue without limit — the pool never rejects anything, so memory grows until the heap is exhausted. There's no back-pressure signal, so the failure appears as a sudden OOM rather than a controlled rejection. The fix is to construct a ThreadPoolExecutor with a bounded queue and an explicit RejectedExecutionHandler so overload is visible and handled.
Real World
Every request-processing service, batch worker, and async pipeline needs this: graceful shutdown so in-flight work drains on deploy (and the JVM actually exits), plus bounded queues so a traffic spike triggers back-pressure or a 503 instead of a heap death spiral. The unbounded-queue OOM is a genuinely common production incident.
Interviewer's Expectation
Keywords they're listening for:
- shutdown vs shutdownNow
- awaitTermination with timeout
- bounded queue + rejection policy
- CallerRunsPolicy back-pressure
- avoid unbounded Executors.newFixedThreadPool
Common Mistakes
- Never calling shutdown (leaks threads, blocks JVM exit)
- Using unbounded-queue Executors factory methods in production
- Calling only shutdownNow and losing queued work
Best Practices
- Construct ThreadPoolExecutor with a bounded queue explicitly
- Follow shutdown → awaitTermination → shutdownNow
- Choose a rejection policy that fits your back-pressure needs
Follow-up Questions
- How do you size a thread pool for CPU vs I/O work?
- What are the four built-in rejection policies?
- Where do exceptions thrown by pooled tasks go?
Continue Learning with AI
Take this question deeper with your favourite AI assistant. Pick a depth, copy the prompt, or open it directly — AI is your learning companion, not a shortcut.
Plain-language foundations
I'm preparing for a software engineering interview and want to understand this from scratch, as a beginner. Topic: Executors (Advanced Java) Interview question: "How do you shut down an ExecutorService cleanly and handle rejected tasks?" Please: 1. Explain the core idea in simple, plain language, using an everyday analogy. 2. Define any technical terms you use. 3. Walk through one small, concrete example. 4. Finish with a single sentence I can easily remember. Keep the tone friendly and assume I'm new to this topic.
Was this answer helpful?
Affiliate links
Tools for Your Developer Workspace
Equipment for a comfortable, productive setup.
As an Amazon Associate I earn from qualifying purchases.
- MonitorView on Amazon : BenQ EW2790U 27-inch Monitor (opens in a new tab)
BenQ EW2790U 27-inch Monitor
- LaptopView on Amazon : Acer Aspire One Laptop (opens in a new tab)
Acer Aspire One Laptop
- Office ChairView on Amazon : Wakefit Gravita Ergonomic Office Chair (opens in a new tab)
Wakefit Gravita Ergonomic Office Chair