Mastering Java ThreadPool Rejection Policies: When and How to Use Them
This article explains the four standard Java ThreadPoolExecutor rejection policies—AbortPolicy, CallerRunsPolicy, DiscardOldestPolicy, and DiscardPolicy—detailing their behavior, suitable scenarios, and providing full code examples, plus guidance on creating custom policies.
Thread pools provide four standard rejection policies.
AbortPolicy (throws exception, handled by caller) : the default policy that throws a RejectedExecutionException, discarding the task; suitable when immediate awareness of rejection is needed.
public static class AbortPolicy implements RejectedExecutionHandler {
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString());
}
}CallerRunsPolicy (caller runs the task) : does not discard or throw; the calling thread executes the task, slowing submission speed; suitable when tasks must not be lost.
public static class CallerRunsPolicy implements RejectedExecutionHandler {
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
r.run();
}
}
}DiscardOldestPolicy (discard oldest task) : discards the oldest task in the queue and resubmits the new one; useful when only the latest tasks matter, such as real‑time data processing.
public static class DiscardOldestPolicy implements RejectedExecutionHandler {
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
if (!e.isShutdown()) {
e.getQueue().poll(); // discard oldest
e.execute(r); // submit new task
}
}
}DiscardPolicy (silently discard) : simply discards the task without throwing an exception; appropriate when loss is acceptable, e.g., logging.
public static class DiscardPolicy implements RejectedExecutionHandler {
public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
// do nothing, discard task
}
}In addition, you can implement a custom rejection policy by implementing the RejectedExecutionHandler interface.
public class CustomRejectedExecutionHandler implements RejectedExecutionHandler {
@Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
// custom handling logic
}
}
ThreadPoolExecutor executor = new ThreadPoolExecutor(
2, 4, 60L, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(2),
new CustomRejectedExecutionHandler()
);Xuanwu Backend Tech Stack
Primarily covers fundamental Java concepts, mainstream frameworks, deep dives into underlying principles, and JVM internals.
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.
