I prefer Callable
s, but in those rare instances you might need a Callable
to be Runnable
, you can easily implement both by adding a run()
method like this to your Callable
.
public void run(){
try{
call();
} catch (Exception e){
e.printStackTrace(); // or however you log errors
}
}
In Java 8, you can also make an interface to do the same thing for you:
public interface CallableRunnable<T> extends Callable<T>, Runnable {
default void run(){
try {
call();
} catch (Exception e) {
e.printStackTrace(); // or however you log errors
}
}
}
Then you just have to change anything that implements Callable<T>
to implements CallableRunnable<T>
.That way, your jobs can always be called by any method that requires either. Of course, if you need specific error handling, you can still override the run() method to handle the exceptions thrown by your call()
method. You could even implement a method to do so:
public interface CallableRunnable<T> extends Callable<T>, Runnable {
default void run(){
try {
call();
} catch (Exception e) {
handleCallExceptions(e);
}
}
default void handleCallExceptions(Exception e){
e.printStackTrace();
}
}
Then any special exception handling only needs to implement its own handleExceptions(Exception)
method... but you don't have to if you don't need to. I prefer this because it allows you to have an implementation that uses your logging framework, etc.