Thursday, March 20, 2008

Using FutureTask

This is what I typically use to convert a sync method to a background Future. The benefit is that it avoids a lot of custom code (creating threads, locks, etc ) and seems simple enough, and it's relatively easy to cut&paste.

Original:

 
Result1 slowMethod1(Param1 p1, Param2 p2) throws Exception1 {
}
Result2 slowMethod2() throws Exception2 {
}

void caller() throws Exception1, Exception2 {
// slowMethod1 and slowMethod2 are independent of each other
Result1 r1 = slowMethod1(p1, p2); // first expensive operation
Result2 r2 = slowMethod2(); // other slow method, not using the result or side-effects of the first
}


New code:

 
Executor bgTasks = Executors.newCachedThreadPool();

Future slowMethod1Future(final Param1 p1, Param2 p2) {
FutureTask fr = new FutureTask(new Callable() {
public Result1 call() {
return slowMethod1(p1, p2);
}
});
bgTasks.execute(fr);
return fr;
}

void caller() {
Future fr = slowMethod1Future(p1, p2);
Result2 r2 = slowMethod2();
try {
Result1 r1 = fr.get();
} catch(InterruptedException e) {
throw new RuntimeException(...);
} catch (ExecutionException e) {
Throwable t = e.getCause();
if (t intanceof Exception1) {
throw (Exception1) t;
} else {
throw new RuntimeException(t);
}
}
}