My consumer doesn't work the way I expect it to. Below is an sscce of what happens in my real program.
In finally!
About to print stacktrace
NullPointerException
stacktrace.In finally!
sun.misc.Unsafe
Program:
import java.lang.Thread.UncaughtExceptionHandler;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
public class ThreadTest implements Runnable {
public static void main(String... args) {
ExecutorService service = Executors.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread newThread = new Thread(r);
newThread.setUncaughtExceptionHandler(new MyExceptionHandler());
return newThread;
}
});
service.submit(new ThreadTest());
}
private static class MyExceptionHandler implements UncaughtExceptionHandler {
@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("About to print stacktrace");
e.printStackTrace();
}
}
@Override
public void run() {
Object foo = null;
try {
while(!Thread.interrupted()) {
Thread.sleep(1000);
System.out.println(foo.toString());
System.out.println("After npe!");
}
} catch(InterruptedException e) {
} finally {
System.out.println("In finally!");
}
}
}
Runnables run inside an Executor don't really throw exceptions which will hit the thread's uncaught exception handler. Instead, the Runnable is wrapped with code which catches Throwable. This is so that a Future can return the exception that was thrown from the task.
as @Gray noted in the comments below, your program is "hanging" because the thread pool thread is keeping the program from exiting. your runnable has completed and the thread pool thread is just waiting for a new task. if you shutdown the thread pool, your program will complete normally (or make the thread pool threads daemon).