Restarting threads using UncaughtExceptionHandler

1. UncaughtExceptionHandler

Java applications have two kind of exceptions – checked exceptions and unchecked exceptions. Checked exceptions must be specified in the throws clause of a method or caught inside them. Unchecked exceptions don’t have to be specified or caught.

When a checked exception is thrown inside the run() method of a Thread object, we have to catch and handle it accordingly, because the run() method doesn’t accept a throws clause. But when an unchecked exception is thrown inside the run() method of a Thread object, the default behavior is to write the stack trace in the console (or log it inside error log file) and exit the program.

Fortunately, Java provides us with a mechanism to catch and treat the unchecked exceptions thrown in a Thread instance to avoid the program crashing. This can be done using UncaughtExceptionHandler.

2. UncaughtExceptionHandler example

In this example, we have created a thread which tries to parse few strings which are supposed to be integers. We have written the run() method such that it throws a “java.lang.NumberFormatException” during it’s execution.

As program does not try to catch this exception, exception floats through JVM level and thread gets killed. This is absolutely normal behavior but it MAY NOT be desired behavior.

2.1. Without UncaughtExceptionHandler

In real life application, you would like to try more than once to perform a critical task even if it failed couple of times. Our example below demonstrate the usecase, first without use of UncaughtExceptionHandler; which causes the thread to die immediately after failure.

class Task implements Runnable
{
   @Override
   public void run()
   {
      System.out.println(Integer.parseInt("123"));
      System.out.println(Integer.parseInt("234"));
      System.out.println(Integer.parseInt("345"));
      System.out.println(Integer.parseInt("XYZ")); //This will cause NumberFormatException
      System.out.println(Integer.parseInt("456"));
   }
}
public class DemoThreadExample
{
   public static void main(String[] args)
   {
      Task task = new Task();
      Thread thread = new Thread(task);
      thread.start();
   }
}

Below is output we get when we run the thread:

123
234
345
Exception in thread "Thread-0" java.lang.NumberFormatException: For input string: "XYZ"
	at java.lang.NumberFormatException.forInputString(Unknown Source)
	at java.lang.Integer.parseInt(Unknown Source)
	at java.lang.Integer.parseInt(Unknown Source)
	at examples.algorithms.sleepingbarber.Task.run(DemoThreadExample.java:24)
	at java.lang.Thread.run(Unknown Source)

2.2. With UncaughtExceptionHandler

Let’s add one UncaughtExceptionHandler implementation to catch any unchecked exception during runtime.

class ExceptionHandler implements UncaughtExceptionHandler
{
   public void uncaughtException(Thread t, Throwable e)
   {
      System.out.printf("An exception has been captured\n");
      System.out.printf("Thread: %s\n", t.getId());
      System.out.printf("Exception: %s: %s\n", e.getClass().getName(), e.getMessage());
      System.out.printf("Stack Trace: \n");
      e.printStackTrace(System.out);
      System.out.printf("Thread status: %s\n", t.getState());
      new Thread(new Task()).start();
   }
}

Now add this exception handler to the thread.

class Task implements Runnable
{
   @Override
   public void run()
   {
      Thread.currentThread().setUncaughtExceptionHandler(new ExceptionHandler());
      System.out.println(Integer.parseInt("123"));
      System.out.println(Integer.parseInt("234"));
      System.out.println(Integer.parseInt("345"));
      System.out.println(Integer.parseInt("XYZ")); //This will cause NumberFormatException
      System.out.println(Integer.parseInt("456"));
   }
}

Now run the above example once again. This will run continuously. In real life, if this task is able to complete it’s task then it will exit without throwing any exception and will complete it’s life cycle.

123
234
345
An exception has been captured
Thread: 1394
Exception: java.lang.NumberFormatException: For input string: "XYZ"
Stack Trace: 
java.lang.NumberFormatException: For input string: "XYZ"
	at java.lang.NumberFormatException.forInputString(Unknown Source)
	at java.lang.Integer.parseInt(Unknown Source)
	at java.lang.Integer.parseInt(Unknown Source)
	at examples.algorithms.sleepingbarber.Task.run(DemoThreadExample.java:24)
	at java.lang.Thread.run(Unknown Source)
Thread status: RUNNABLE
123
234
345
An exception has been captured
Thread: 1395
Exception: java.lang.NumberFormatException: For input string: "XYZ"
Stack Trace: 
java.lang.NumberFormatException: For input string: "XYZ"
	at java.lang.NumberFormatException.forInputString(Unknown Source)
	at java.lang.Integer.parseInt(Unknown Source)
	at java.lang.Integer.parseInt(Unknown Source)
	at examples.algorithms.sleepingbarber.Task.run(DemoThreadExample.java:24)
	at java.lang.Thread.run(Unknown Source)
Thread status: RUNNABLE
123
234
345

3. Conclusion

UncaughtExceptionHandler helps you to run a thread in a way such that it will run until it’s task is done. This can be achieved through other multi-threading concepts as well.

Please note that UncaughtExceptionHandler can be used for making logging more robust only as well without restarting the thread because often default logs don’t provide enough information about the context when thread execution failed.

Happy Learning !!

Leave a Comment

  1. UncaughtExceptionHandler concept is not working for Executor..

    then what is way ? could you please tell me.
    please correct me if i am wrong

    Reply
  2. Hi Lokesh,

    Also default exception handler imp…

    Thread thread = new Thread(task);
    thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
    @Override
    public void uncaughtException(Thread t, Throwable e) {
    System.out.printf(“An exception has been captured\n”);
    System.out.printf(“Thread: %s\n”, t.getId());
    System.out.printf(“Exception: %s: %s\n”,
    e.getClass().getName(), e.getMessage());
    System.out.printf(“Stack Trace: \n”);
    e.printStackTrace(System.out);
    System.out.printf(“Thread status: %s\n”, t.getState());
    new Thread(new Task()).start();
    }
    });
    thread.start();

    Wish you a prosperous happy new year 2015

    Regards,
    Himansu

    Reply
  3. Nice post!!
    Well why can’t we initiate new thread execution in catch block of run instead? I know it’s not advisable to have try/catch block for unchecked exceptions, but doing so will serve our purpose.
    Like below,

    @Override
    public void run()
    {
    // Thread.currentThread().setUncaughtExceptionHandler(new ExceptionHandler());
    try{
    System.out.println(Integer.parseInt(“123”));
    System.out.println(Integer.parseInt(“234”));
    System.out.println(Integer.parseInt(“345”));
    System.out.println(Integer.parseInt(“XYZ”)); //This will cause NumberFormatException
    System.out.println(Integer.parseInt(“456”));
    }catch(Exception e){
    System.out.println(“Exception occured”);
    e.printStackTrace();
    new Thread(new Task()).start();
    }
    }

    Reply
      • If catch i not advisable then why uncaughtexception handler is advisable? I am confused here, both will serve the same purpose – catching unchecked exceptions and doing remedy. So why one is not advisable and other is recommanded?

        Reply
          • That’s not true.. if e.g. you know it is possible user input might not be numeric, you can specifically catch NumberFormatException — there’s nothing wrong with this (aside from, in the example I gave, the fact you should check if the input is numeric first and avoid the exception) — and it works without catching Exception or Throwable.

          • This is very specific scenario and I will call it input validation. If at this step, program fails – I will call it a bad design.
            Further, technically both approaches serve the same purpose, its more of choice matter.

Leave a Comment

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Our Blogs

REST API Tutorial

Dark Mode

Dark Mode