我已經從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