Introduction :

There is always a scenario in a development process where a piece of any code/line (e.g.,business logic) throws some unchecked/runtime exception which is not possible to handle as we are not sure about the user input. In that case the thread responsible for executing that piece of code dies off and the assigned task remain unfinished.

Due to this the output may not be consistent and the reuslt can be pretty random.

Let us take the below example,


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 WithoutExceptionHandlerExample
{
public static void main(String[] args)
{
Task task = new Task();
Thread thread = new Thread(task);
thread.start();
}
}

Below is the output for the programme:-
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)

Use of UncaughtExceptionHandler

To overcome such scenario, we can use UncaughtExceptionHandler introduces in JDK 1.5
Java provides us with a mechanism to catch and treat the unchecked exceptions thrown in a Thread object to avoid abrupt termination of the program.
This can be done using UncaughtExceptionHandler.

All you need to follow the steps below:-
• Create any class and implement UncaughtExceptionHandler interface.
Override the abstract method with the following signature:-

public void uncaughtException(Thread t, Throwable e) {
//Write the logic/code to start the thread.
//ex: new Thread.start();
}

• Add the below line on the run method

Thread.currentThread().setUncaughtExceptionHandler

(new HandlenUncheckedException()); 

Please note that this line has to be written before the expected exception to occur.
Since we are not sure about the line which may be the reason of the exception so it is good practice to write as the first line of the run method.
When any unchecked exception is encountered the control goes to the overridden method and there you can write the logic to start a thread.

Below is the source code to understand the concept.


package com.thread;

import java.lang.Thread.UncaughtExceptionHandler;

public class WithExceptionHandlerExample{
public static void main(String[] args) {
System.out.println("with exception");
ThreadHandle t1 = new ThreadHandle();
Thread t = new Thread(t1);
t.start();

}

}

class ThreadHandle implements Runnable {

@Override
public void run() {
System.out.println(Integer.parseInt("123"));
System.out.println(Integer.parseInt("123"));
Thread.currentThread().setUncaughtExceptionHandler(new HandlenUncheckedException());

System.out.println(Integer.parseInt("sho"));
System.out.println(Integer.parseInt("123"));

System.out.println(Thread.currentThread().getName() + ":"
+ Thread.currentThread().getState());
System.out.println();
}
}

class HandlenUncheckedException implements UncaughtExceptionHandler{

@Override
public void uncaughtException(Thread t, Throwable e) {
System.out.println("An exception has been captured\n");
System.out.println("Thread:\t"+ t.getId());
System.out.println("Exception:\t"+e.getClass().getName()+":"+ e.getMessage());
System.out.println("Stack Trace: \n");
e.printStackTrace(System.out);
System.out.println("Thread status:\t"+ t.getState());
new Thread(new ThreadHandle()).start();
}
}

Below is the output for the programme:-
123
123
An exception has been captured
Thread: 8043
Exception: java.lang.NumberFormatExceptionStack Trace:
java.lang.NumberFormatException: For input string: "sho"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at com.thread.ThreadHandle.run(WithExceptionHandlerExample.java:24)
at java.lang.Thread.run(Unknown Source)
Thread status: RUNNABLE
123
123
An exception has been captured
Thread: 8044
Exception: java.lang.NumberFormatExceptionStack Trace:
java.lang.NumberFormatException: For input string: "sho"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at com.thread.ThreadHandle.run(WithExceptionHandlerExample.java:24)
at java.lang.Thread.run(Unknown Source)
Thread status: RUNNABLE

 

As you can see from the above example whenever any exception is encountered JVM calls uncaughtException method. Using this method we can get all the related information pertaining to the exception and thread. In the overridden method you can write the logic to start a new thread.

Hope this helps, please drop your questions in the comment box.

Thanks.