线程池执行器中取消任务

3

我实例化了ThreadPoolExecutor并将异步任务提交到池中,得到了Future对象,然后尝试取消任务,但取消操作不起作用...

该任务与数据库调用相关。

代码如下:

private ThreadPoolExecutor _scheduledThreadPool;
_scheduledThreadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(_poolSize,   factory);
Future<Object> task = _scheduledThreadPool.submit(task);
tasks.cancel(true);

在上述代码之后,我观察到_scheduledThreadPool.getQueue()返回的是空的。
我已经尝试了几天,但还没有成功。
请帮助我如何在ThreadPoolExecutor中单独取消任务。
谢谢。
3个回答

3

如果在调用cancel()时任务已经在运行,这似乎是您所遇到的情况-那么这不会“神奇地”保证任务将以您期望的方式停止运行。运行任务的线程将被中断,并且执行任务的代码必须使用您期望的行为来处理它。


谢谢您的回答。我想使用删除方法,尝试了以下内容:BlockingQueue queue = _scheduledThreadPool.getQueue(); _scheduledThreadPool.remove(runnabletaskFromQueue); 但是队列返回了空结果。请问您能否提供任何建议来解决这个问题。 - Sunil Kumar
1
使用cancel()是可以的,但你需要确保你的任务能够响应中断:换句话说,它基本上要花费所有时间调用那些被定义为抛出InterruptedException的方法,或者定期检查Thread.interrupted()。http://docs.oracle.com/javase/7/docs/api/java/lang/InterruptedException.html - Neil Coffey
是的,现在它正在工作。我尝试了以下代码: try { try {
process.get(5, TimeUnit.SECONDS); } catch (InterruptedException e) { process.cancel(true); } } catch (TimeoutException e) { process.cancel(true); } 并且定期检查 if (Thread.currentThread().isInterrupted()),然后从进程中返回。非常感谢您的帮助。
- Sunil Kumar

0

你可以尝试:

_scheduledThreadPool.getQueue().clear();


请解释为什么你的答案解决了问题。查看[答案]。 - JimHawkins

0

这里有一个 Future 对象:

Future<Object> task = _scheduledThreadPool.submit(task);

ThreadPoolExecutor 使用 FutureTask 作为默认的 Future 实现。而 FutureTask 使用线程中断 来取消任务。因此,它会在工作线程上调用 Thread.interrupt

但是,要发生取消操作,任务必须对中断有响应。换句话说,它必须通过调用 Thread.interrupted/Thread.currentThread().isInterrupted 来检查当前线程是否被中断。例如,我们在循环中检查中断状态:

final Runnable task = () -> {
    while (!Thread.currentThread().isInterrupted()) {
        // Do work.
    }
}

或者,任务必须被阻塞在遵守中断的代码上,例如LinkedBlockingQueue.take。标准库通常在检测到中断时抛出InterruptedException异常。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接