Saturday, September 24, 2011

Throw an exception from a Java thread and handle it on the parent thread

Let say you want to compute a result in the background of a program. Usually it's achieved by encapsulate the task inside a Runnable object and run it in a new thread. If an error occurs during the process you want your program to be notified and handle errors. But unfortunately the run() method of the Runnable interface doesn't allow to throw exceptions.

In this post I will demonstrate a way to achieved that based on Callable and Executors.




The Callable Interface is very similar to Runnable, here is an implementation example :

import java.util.concurrent.Callable;
public class MyTask implements Callable<Integer> {
private int numerator;
private int denominator;
public MyTask(int n, int d) {
this.numerator = n;
this.denominator = d;
}
@Override
//The call method may throw an exception
public Integer call() throws Exception {
if (denominator == 0)
throw new Exception("cannot devide by zero");
else
return numerator/denominator;
}
}
view raw MyTask.java hosted with ❤ by GitHub
To run this Callable task we need a Executors. The submit() method of the Executor take a Callable and return a Future which represents the result of the task. Finally we can call the get() method of Future to get the value of the result. If the call() method has thrown an exception get() will throw an ExecutionException which contains the original exception.
Here is an example :

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
//Build a task and an executor
MyTask task = new MyTask(2, 0);
ExecutorService threadExecutor = Executors.newSingleThreadExecutor();
try {
//Compute the task in a separate thread
int result = (int) threadExecutor.submit(task).get();
System.out.println("The result is " + result);
}
catch (ExecutionException e) {
//Handle the exception thrown by the child thread
if (e.getMessage().contains("cannot devide by zero"))
System.out.println("error in child thread caused by zero division");
}
catch (InterruptedException e) {
//This exception is thrown if the child thread is interrupted.
e.printStackTrace();
}
}
}
view raw Main.java hosted with ❤ by GitHub

1 comment:

  1. In that case main thread never done all task before created thread execution finished.

    ReplyDelete