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.