Java 删除ThreadPoolExecutor的所有排队任务

Java 删除ThreadPoolExecutor的所有排队任务,java,multithreading,threadpool,executorservice,executor,Java,Multithreading,Threadpool,Executorservice,Executor,关于这个问题,我有一个相当简单的问题。我有以下情况:我必须使用队列中的对象,为它们创建适当的辅助任务,并将它们提交给ThreadPoolExecutor。这很简单。但是在关闭场景中,许多工作人员可能排队等待执行。由于其中一个任务可能会运行一个小时,并且我希望应用程序能够相对快速地正常关闭,因此我希望放弃ThreadPoolExecutor中所有排队的任务,而已经处理的任务应该正常完成 ThreadPoolExecutor文档有一个方法,但只允许删除特定任务。仅适用于已取消的未来任务。我的想法是清

关于这个问题,我有一个相当简单的问题。我有以下情况:我必须使用队列中的对象,为它们创建适当的辅助任务,并将它们提交给ThreadPoolExecutor。这很简单。但是在关闭场景中,许多工作人员可能排队等待执行。由于其中一个任务可能会运行一个小时,并且我希望应用程序能够相对快速地正常关闭,因此我希望放弃ThreadPoolExecutor中所有排队的任务,而已经处理的任务应该正常完成

ThreadPoolExecutor文档有一个方法,但只允许删除特定任务。仅适用于已取消的未来任务。我的想法是清除包含所有排队任务的队列。ThreadPoolExecutor提供对此内部队列的访问,但文档说明:

方法getQueue()允许访问 用于监视的工作队列 以及调试。这种方法的使用 对于任何其他目的,强烈反对 气馁

因此,抓住这个队列并清除它不是一个选项。此外,文档的这一部分还说:

提供了两种方法, 删除(java.lang.Runnable)和清除() 可用于协助存储 当大量 排队的任务将被取消

怎么做?当然,我可以维护提交给执行器的所有任务的列表,在关机的情况下,我迭代所有条目,并使用remove()方法将它们从ThreadPoolExecutor中删除。。。但是来吧,这是一种浪费内存和维护此列表的麻烦。(例如,删除已执行的任务)


我感谢任何提示或解决方案

由于做得不够,做得太多,我想你必须在中间写点东西:记住所有提交的任务,并在调用
shutdown()

之后(或之前)手动删除它们。Bombe的答案正是你想要的
shutdownNow()
使用nuke和pave方法停止一切。这是您能做的最好的事情,除了将您正在使用的
ThreadPoolExecutor
的实现子类化之外。

一个疯狂而不干净的解决方案可能会起作用(不是真正经过深思熟虑或测试的)就是覆盖
中断()
您的工作任务,只有在设置了某些全局值的情况下,当shutdownNow()调用
中断()
时,才会拒绝关机


这应该允许您使用
shutdownNow()
no?

告诉您的线程池要关闭,getQueue,对于每个将结果放入单个Runnable的线程,使用remove方法删除每个Runnable。根据队列的类型,您可能能够根据返回值提前停止删除


基本上,这就是抓取队列并清除它,只通过有效的方法进行清除。不用手动记住所有提交,而是使用线程池已经记住所有提交的事实。但是,您可能需要制作队列的防御性副本,因为我认为这是一个实时视图,因此,如果您在实时视图上迭代/进行搜索,则删除可能会导致并发修改异常。

我以前使用的是具有长时间运行线程的应用程序。我们在关机时这样做

BlockingQueue<Runnable> queue = threadPool.getQueue();
List<Runnable> list = new ArrayList<Runnable>();
int tasks = queue.drainTo(list);
BlockingQueue queue=threadPool.getQueue();
列表=新的ArrayList();
int tasks=queue.drainTo(列表);

列表将保存到一个文件中。启动时,列表会添加回池中,这样我们就不会丢失任何工作。

您是否考虑过包装Executor服务?创建一个

CleanShutdownExecutorService implements Executor 

它将所有调用委托给另一个执行者,但将未来保留在自己的列表中。CleanShutdownExecutorService可以有一个cancelRemainingTasks()方法,该方法调用shutdown(),然后对其列表中的所有未来调用cancel(false)。是否
等待终止(长超时,时间单位)
在关闭后工作

executor.shutdown();
executor.awaitTermination(60,TimeUnit.SECONDS)

您可以尝试
allowCoreThreadTimeOut(true)

这是一个老问题,但如果这对其他人有帮助:您可以在调用shutdown()时设置一个可变布尔值,如果在真正开始之前设置了该布尔值,则可以终止每个提交的任务。这将允许真正开始完成的任务,但会阻止排队的任务开始其实际活动。

您可以创建自己的任务队列,并将其传递给
ThreadPoolExecutor
构造函数:

int poolSize = 1; // number of threads
BlockingQueue<Runnable> queue = new ArrayBlockingQueue<>();
Executor executor = new ThreadPoolExecutor(poolSize, poolSize, 0L, TimeUnit.MILLISECONDS, queue);

“启动有序关机,执行以前提交的任务,但不接受新任务。”我提交了几个不应再执行的任务。但是正在执行的任务不应该结束。您编辑了答案,因此我的评论不再完全有效。然而,Shutdownow()文档指出:“尝试停止所有正在执行的任务。”这不是我想要的哦,对了,我读得太多了。那么,我想你唯一的选择就是记住所有提交的
Runnable
s并手动删除它们。我将相应地进行编辑。对我的问题进行了很好的补充。:-)我认为任务的持久性不是问题。但您的添加可能会帮助其他人,谢谢!:)我不确定这是正确的方法。如果您通过shutdown()关闭,它将一直等待,直到所有任务(甚至排队的任务)终止;如果您使用shutdownNow()关闭,则该方法已返回排队的任务列表。仅供参考。这可能是最干净的方法,因此我接受这个答案。:-)甚至我都希望已经有这样的事情了。。。所以:让我们来编写代码。:-)你应该发展你的答案,明确你实际上是在回答OP。
queue.clear();