Saturday, February 9, 2008

Java Threads and Exception Handling

Exception handling with threads seems to be a topic that can be confusing for people. So here I offer an example of how it can be done.

The "Callable" interface is provided exactly for this purpose. The code below creates a thread once without throwing an exception and creates a thread a second time in order to throw an exception. There isn't much to it really, once you see it done, but getting there can be difficult.

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

public class Main {

public static void main(String args[]) {
// create an executor service to execute our threads (tasks)
ExecutorService executor = Executors.newCachedThreadPool();

// create a new thread/task
FutureTask task = new FutureTask(new SomeThread(false));
executor.submit(task); // execute the thread
// we must shutdown the executor service in order to know when all
// submitted tasks have completed..
executor.shutdown();

try {
// wait a maximum of 5 seconds for the thread to terminate
// (normally or with an error).
executor.awaitTermination(5, TimeUnit.SECONDS);
// output whatever value the thread returned.
System.out.println("The task returned: " + task.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}

executor = Executors.newCachedThreadPool();
task = new FutureTask(new SomeThread(true));
executor.submit(task);

executor.shutdown();
try {
executor.awaitTermination(5, TimeUnit.SECONDS);
// The error is returned when we call the .get() method.
System.out.println("The task returned: " + task.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
} // end of main.

static class SomeThread implements Callable {
boolean throwAnError = false;

public SomeThread(boolean throwAnError) {
this.throwAnError = throwAnError;
}

public String call() throws Exception {
System.out.println("Sleeping...");
Thread.sleep(2000);
System.out.println("Done sleeping!");

if (throwAnError) {
throw new Exception("Oh no, an exception!");
}

return "some return value";
}
} // end of SomeThread.
}

Of course there are some intricacies, but this should get anyone started. If this gets you excited the next exciting thing may be a BlockingQueue.

No comments: