我已经延长了FutureTask
from java.util.concurrent
提供回调来跟踪提交给任务的执行情况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);
}
}
现在,我看到的是任务是否已提交,但最终排队并且我cancel(true);
任务——run()
方法仍然被调用 - 并且FutureTask.run()
(可能)检查任务是否已取消并且不调用包装的可调用对象。
我应该这样做吗?
@Override
public void run() {
if(!isCancelled()) {
statusHandler.TaskRunning(this);
super.run();
}
}
或者我还是应该打电话super.run()
?这两种方法似乎都容易受到检查取消和执行某些操作之间的竞争条件的影响......任何想法都值得赞赏。
你说得对,那里有一场比赛。FutureTask#done()
将被称为最多一次,所以如果任务在通过运行之前已经被取消RunnableFuture#run()
,您将会错过以下电话:FutureTask#done()
.
您是否考虑过一种更简单的方法,该方法始终发出一组对称的配对调用ITaskStatusHandler#taskRunning()
and ITaskStatusHandler#taskCompleted()
,像这样?
@Override
public void run() {
statusHandler.TaskRunning(this);
try {
super.run();
finally {
statusHandler.TaskCompleted(this);
}
}
Once RunnableFuture#run()
被称为,确实你的任务正在运行,或者至少试图被运行。一次FutureTask#run()
完成后,您的任务不再运行。碰巧的是,在取消的情况下,过渡(几乎)是立即的。
试图避免打电话ITaskStatusHandler#taskRunning()
如果内部Callable
or Runnable
永远不会被调用FutureTask#run()
将要求您在之间建立一些共享结构Callable
or Runnable
和FutureTask
-派生类型本身,这样当你的内部函数第一次被调用时,你可以设置一些标志来表明外部函数FutureTask
-派生类型可以观察为闩锁,表明是的,该函数确实开始运行before已被取消。但是,到那时,您必须承诺致电ITaskStatusHandler#taskRunning()
,所以这种区别不是很有用。
我最近一直在努力解决类似的设计问题,最后决定采用对称设计before and 手术后在我的重写中FutureTask#run()
method.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)