我已经从java.util.concurrent
扩展FutureTask
来提供回调以跟踪提交给ExecutorService
的任务的执行情况。现在扩展FutureTask,如何处理取消
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);
}
}
,我所看到的是,如果该任务被提交,但最终排队,我cancel(true);
的任务 - run()
方法仍然被调用 - 和FutureTask.run()
(可能)会检查任务被取消,并没有按不打电话给包装的可回收物品。
我应该如
@Override
public void run() {
if(!isCancelled()) {
statusHandler.TaskRunning(this);
super.run();
}
}
还是应该叫super.run()
?这两种方法似乎都容易受到检查取消和做某件事情之间的竞争条件的影响..任何想法都会受到赞赏。
我假设在finally子句中的调用应该是statusHandler.TaskCompleted(this);有没有运行方法不会被调用,但done()方法呢? – nos 2009-11-27 21:20:51
感谢您发现错误。我在finally块中修复了这个呼叫。 是的,可以在不调用run()的情况下调用done()。请参阅FutureTask#Sync#innerCancel(布尔值)。在那里,如果任务尚未完成,包括它从未开始运行,您可以看到done()将被调用。请注意,对于任何FutureTask实例,done()都将被调用0或1次:如果run()和cancel()都不会被调用,则返回0。 – seh 2009-11-27 21:52:50
似乎,如果你将它提交给执行者完成()将被调用,如果该任务在执行之前被取消 - 尽管执行者不知道这一点。执行者只知道可运行的/可调用的。因此,run()会在最终变成可运行的时候被调用,在这种情况下,FutureTask#run()基本上什么都不做。 – nos 2009-11-27 22:14:54