DerMike DerMike - 3 months ago 44
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

java.lang.Thread
) the
UncaughtExceptionHandler
is called appropriately. However, when I use an
ExecutorService
with a
ThreadFactory
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() {

@Override
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() {

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

// create Threadpool

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

// create Runnable

Runnable runnable = new Runnable() {

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

// create Callable

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

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

// a) submitting Runnable to threadpool
threadPool.submit(runnable);

// b) submit Callable to threadpool
threadPool.submit(callable);

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

threadPool.shutdown();
System.out.println("Done.");
}
}


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

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.