DerMike DerMike - 1 year ago 122
Java Question

Why is UncaughtExceptionHandler not called by ExecutorService?

I've stumbled upon a problem, that can be summarized as follows:

When I create the thread manually (i.e. by instantiating

) the
is called appropriately. However, when I use an
with a
the handler is ommited. What did I miss?

public class ThreadStudy {

private static final int THREAD_POOL_SIZE = 1;

public static void main(String[] args) {

// create uncaught exception handler

final UncaughtExceptionHandler exceptionHandler = new UncaughtExceptionHandler() {

public void uncaughtException(Thread t, Throwable e) {
synchronized (this) {
System.err.println("Uncaught exception in thread '" + t.getName() + "': " + e.getMessage());

// create thread factory

ThreadFactory threadFactory = new ThreadFactory() {

public Thread newThread(Runnable r) {
// System.out.println("creating pooled thread");
final Thread thread = new Thread(r);
return thread;

// create Threadpool

ExecutorService threadPool = Executors.newFixedThreadPool(THREAD_POOL_SIZE, threadFactory);

// create Runnable

Runnable runnable = new Runnable() {

public void run() {
// System.out.println("A runnable runs...");
throw new RuntimeException("Error in Runnable");

// create Callable

Callable<Integer> callable = new Callable<Integer>() {

public Integer call() throws Exception {
// System.out.println("A callable runs...");
throw new Exception("Error in Callable");

// a) submitting Runnable to threadpool

// b) submit Callable to threadpool

// c) create a thread for runnable manually
final Thread thread_r = new Thread(runnable, "manually-created-thread");


I expect: Three times the message "Uncaught exception..."

I get: The message once (triggered by the manually created thread).

Reproduced with Java 1.6 on Windows 7 and Mac OS X 10.5.

Answer Source

Because the exception does not go uncaught.

The Thread that your ThreadFactory produces is not given your Runnable or Callable directly. Instead, the Runnable that you get is an internal Worker class, for example see ThreadPoolExecutor$Worker. Try System.out.println() on the Runnable given to newThread in your example.

This Worker catches any RuntimeExceptions from your submitted job.

You can get the exception in the ThreadPoolExecutor#afterExecute method.