当前位置: 首页 > 知识库问答 >
问题:

ExecutorService的未来任务不会真正取消

魏冷勋
2023-03-14

我将未来从ExecutorService推送到哈希映射中。稍后,我可以在散列图中调用Futures上的cancel。虽然结果是真的,但我后来在可调用过程中遇到了断点,好像Future cancel()没有任何效果。我认为这里可能有两个不同的引用(即使在中断时引用ID是一样的),但我想知道是否有一些专家可以插话。代码如下所示:

ExecutorService taskExecutor = Executors.newCachedThreadPool();
Map <String, Future<Object>> results = new HashMap <String, Future<Object>>();      

Future<Object> future = taskExecutor.submit(new MyProcessor(uid));
results.put(uid, future);

我允许继续处理(这是一个在传入任务时提交任务的循环),稍后我可能会尝试通过调用此方法从外部源取消:

public static synchronized boolean cancelThread(String uid) {
    Future<Object> future = results.get(uid);
    boolean success = false;
    if (future != null) {
        success = (future.isDone() ? true : future.cancel(true));
        if (success)
            results.remove(uid);
    }
    return success;     
}

但我仍然在MyProcessor中遇到一条“未取消”的路径。在future之后调用()。调用了cancel(),即它实际上没有被取消。

这件事我哪里做错了?有没有更好的办法?

共有2个答案

易淳
2023-03-14

FutureTask:: 布尔取消(boolean mayInterrupIfRrun)将在当前正在运行的线程上执行中断

FutureTask.java
public boolean cancel(boolean mayInterruptIfRunning) {
    if (!(state == NEW &&
          UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
              mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
        return false;
    try {    // in case call to interrupt throws exception
        if (mayInterruptIfRunning) {
            try {
                Thread t = runner;
                if (t != null)
                    t.interrupt();     ////////////HERE/////////////
            } finally { // final state
                UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
            }
        }
    } finally {
        finishCompletion();
    }
    return true;
}

JavaDoc说下面是中断

html" target="_blank">public void interrupt()中断此线程。除非当前线程中断自身(这是始终允许的),否则将调用此线程的checkAccess方法,这可能会导致引发SecurityException。

如果该线程在调用对象类的wait()、wait(long)或wait(long,int)方法时被阻塞,或者在调用该类的join()、join(long)、join(long,int)、sleep(long)或sleep(long,int)方法时被阻塞,那么它的中断状态将被清除,并将接收到InterruptedException。

如果该线程在可中断通道上的I/O操作中被阻塞,那么该通道将被关闭,线程的中断状态将被设置,线程将收到ClosedByInterruptException。

如果此线程在选择器中被阻塞,则将设置线程的中断状态,并立即从选择操作返回,可能返回非零值,就像调用了选择器的唤醒方法一样。

如果前面的条件都不成立,那么将设置该线程的中断状态。

中断不活动的线程不需要有任何效果。

抛出:SecurityException-如果当前线程无法修改此线程

结束;取消FutureTask只有在线程被阻塞时才会产生影响(在调用等待()时,...)否则开发人员有责任检查Thread.currentThread(). isInterunc()退出;同时执行非阻塞操作。

孙德本
2023-03-14

我后来在Callable过程中碰到了断点,就好像未来取消()没有效果一样。

未来。取消(true)删除队列中尚未运行的作业,但如果作业已在运行,则执行与线程等效的操作。在运行作业的线程上中断()。这将设置线程上的中断位,并导致任何睡眠、等待和其他方法引发中断异常。

重要的是要认识到它不会停止线程。您需要主动检查线程循环中的中断标志,或正确处理中断异常。

有关更多详细信息,请参阅此处我的SO回答:如何使用线程的id挂起线程?

 类似资料:
  • 问题内容: 我将我的期货从ExecutorService推送到哈希图中。以后,我可以从哈希图中调用期货取消。尽管结果是正确的,但后来我在Callable过程中命中了断点,就好像Future cancel()无效。我认为这里可能是两个不同的引用的情况(即使在断点时引用ID被列出为相同),但我想知道是否有些专家可以插手。代码如下所示: 我允许处理继续进行(这是一个在任务传入时提交任务的循环),以后我可

  • 我正在使用Java ExecutorService(ThreadPool)执行一个任务&更新UI,而特定的活动处于前台(可见)。 问题:我想要的是当用户切换到另一个活动时,我想要停止/取消所有的任务(无论是排队的还是正在运行的)。为此,我必须使用ExecutorService shutdown/shutdownNow方法,或者在调用isDone()检查未来对象状态后,对ExecutorServic

  • 我应该创建一个从迭代器中提取下一个任务的任务吗?或者有什么更好的方法来实现这一点?

  • 问题内容: 我正在尝试使用Java的类来运行大量具有固定数量线程的重量级任务。每个任务都有很多地方,在这些地方可能会由于异常而失败。 我已经继承了子类,并且重写了应该提供运行任务时遇到的任何未捕获异常的方法。但是,我似乎无法使其工作。 例如: 该程序的输出是“一切都很好-情况正常!” 即使唯一提交给线程池的Runnable引发异常。任何线索这里发生了什么? 谢谢! 问题答案: 提交Runnable

  • 我在Camunda有一些复杂的过程,在所有这些过程的最后都有一个接收任务。在接收任务中,我们显示了流程变量的摘要。问题是接收任务是可选的,它不是用户的强制任务,所以用户可以在没有完成接收任务的情况下退出进程。在这种情况下,流程实例的状态保持在活动状态,这会导致我们的报告出现一个糟糕的视图。 我们的目标有什么解决方案吗? 我展示了一个示例进程,它具有我们所有进程的格式。第一步是用户必须完成的数据输入

  • 我已经使用ExecutorService实现了超时任务。在下面的方法中,我正在提交超时任务,如果它在给定的时间内超时,我将取消该任务并关闭执行器。 它运行得很好,我没有任何问题。 然而,我想知道这是否是最好的代码设计。我只是想知道如果使用ExecutorService返回的未来是否会更好。submit()获取可调用函数的返回值或超时超时任务。例如 我正在使用JDK7。