Handling Exceptions in Thread - Thread.UncaughtExceptionHandler

A task queued with execute() that generates some Throwable will cause the UncaughtExceptionHandler for the Thread running the task to be invoked. The default UncaughtExceptionHandler, which typically prints the Throwable stack trace to System.err, will be invoked if no custom handler has been installed.

On the other hand, a Throwable generated by a task queued with submit() will bind the Throwable to the Future that was produced from the call to submit(). Calling get() on that Future will throw an ExecutionException with the original Throwable as its cause (accessible by calling getCause() on the ExecutionException).


If you want to process exceptions thrown by the task, then it is generally better to use Callable rather than Runnable.
Callable.call() is permitted to throw checked exceptions, and these get propagated back to the calling thread:

Future future = executorService.submit(new Callable(){
    public Object call() throws Exception {
        System.out.println("Asynchronous Callable");
        return "Callable Result";
    }
});

try {
   future.get();
} catch (ExecutionException ex) {
   ex.getCause().printStackTrace();
}
 


If Callable.call() throws an exception, this will be wrapped in an ExecutionException and thrown by Future.get().
This is likely to be much preferable to subclassing ThreadPoolExecutor. It also gives you the opportunity to re-submit the task if the exception is a recoverable one.



With normal Thread

public class Task implements Runnable {
    @Override
    public void run() {
        System.out.println("Inside Task >> run() - throw RuntimeException");
        throw new RuntimeException();
    }
}


Test Class

public class TestUncaughtExceptionHandler {

    public static void main(String[] args) {
        Thread thread = new Thread(new Task());
        thread.start();
       
        thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
            public void uncaughtException(Thread myThread, Throwable e) {
                System.out.println(myThread.getName() + " throws exception: " + e);
            }
        });

    }
}


Output
Inside Task >> run() - throw RuntimeException
Thread-0 throws exception: java.lang.RuntimeException

0 comments: