gpt4 book ai didi

java - 扩展FutureTask,如何处理cancel

转载 作者:搜寻专家 更新时间:2023-10-31 19:58:59 26 4
gpt4 key购买 nike

我从 java.util.concurrent 扩展了 FutureTask 以提供回调来跟踪提交给 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()ITaskStatusHandler#taskCompleted() ,像这样?

@Override
public void run() {
statusHandler.TaskRunning(this);
try {
super.run();
finally {
statusHandler.TaskCompleted(this);
}
}

一次RunnableFuture#run()被称为,你的任务确实在运行,或者至少试图运行。一次FutureTask#run()完成后,您的任务不再运行。碰巧在取消的情况下,转换(几乎)是立即的。

试图避免调用 ITaskStatusHandler#taskRunning()如果内部CallableRunnable从未被 FutureTask#run() 调用将要求您在 Callable 之间建立一些共享结构或 RunnableFutureTask -派生类型本身,这样当你的内部函数第一次被调用时,你设置了一些标志,表明外部 FutureTask -derived 类型可以作为闩锁观察,表明是的,该函数确实在被取消之前 开始运行。但是,到那时,您必须 promise 调用 ITaskStatusHandler#taskRunning() ,所以区别不是那么有用。

我最近一直在为类似的设计问题而苦苦挣扎,最终在我重写的 FutureTask#run() 中解决了对称的beforeafter operations方法。

关于java - 扩展FutureTask,如何处理cancel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1808776/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com