I've extended FutureTask from java.util.concurrent to provide callbacks to track the execution of tasks submitted to an ExecutorService.
public class StatusTask<V> extends FutureTask<V> {
private final ITaskStatusHandler<V> statusHandler;
public StatusTask(Callable<V> callable, ITaskStatusHandler<V> statusHandler){
super(callable);
if (statusHandler == null)
throw new NullPointerException("statusHandler cannot be null");
this.statusHandler = statusHandler;
statusHandler.TaskCreated(this);
}
@Override
public void run() {
statusHandler.TaskRunning(this);
super.run();
}
@Override
protected void done() {
super.done();
statusHandler.TaskCompleted(this);
}
}
Now, what I see is if the task is submitted, but ends up queued and i cancel(true); the task - the run() method still gets called - and the FutureTask.run() (likely) checks that the task is cancelled and doesn't call the wrapped callable.
Should I do e.g.
@Override
public void run() {
if(!isCancelled()) {
statusHandler.TaskRunning(this);
super.run();
}
}
Or should I still call super.run() ? Both these approaches seems susceptible to race conditions in between checking for cancellation and doing something about it.. any thoughts appreciated.