使用Java ExecutorService,如何完成主动执行任务但停止等待任务的处理? [英] With a Java ExecutorService, how do I complete actively executing tasks but halt the processing of waiting tasks?

查看:318
本文介绍了使用Java ExecutorService,如何完成主动执行任务但停止等待任务的处理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用ExecutorService(ThreadPoolExecutor)来运行(和排队)很多任务。我试图编写一些尽可能优雅的关闭代码。

I am using an ExecutorService (a ThreadPoolExecutor) to run (and queue) a lot of tasks. I am attempting to write some shut down code that is as graceful as possible.

ExecutorService有两种关闭方式:

ExecutorService has two ways of shutting down:


  1. 我可以调用 ExecutorService.shutdown()然后 ExecutorService.awaitTermination(...)

  2. 我可以致电 ExecutorService.shutdownNow()

  1. I can call ExecutorService.shutdown() and then ExecutorService.awaitTermination(...).
  2. I can call ExecutorService.shutdownNow().

根据JavaDoc, shutdown 命令:

According to the JavaDoc, the shutdown command:

Initiates an orderly shutdown in which previously submitted
tasks are executed, but no new tasks will be accepted.

以及 shutdownNow 命令:

Attempts to stop all actively executing tasks, halts the
processing of waiting tasks, and returns a list of the tasks that were
awaiting execution.

我想要这两个选项之间的东西。

I want something in between these two options.

我想拨打以下命令:

   a。完成当前活动的任务(例如关闭)。

   b。暂停等待任务的处理(如 shutdownNow )。

I want to call a command that:
  a. Completes the currently active task or tasks (like shutdown).
  b. Halts the processing of waiting tasks (like shutdownNow).

例如:假设我有一个包含3个线程的ThreadPoolExecutor 。它目前在队列中有50个任务,前3个正在运行。我想允许完成这3个活动任务,但我不希望剩余的47个任务开始。

For example: suppose I have a ThreadPoolExecutor with 3 threads. It currently has 50 tasks in the queue with the first 3 actively running. I want to allow those 3 active tasks to complete but I do not want the remaining 47 tasks to start.

我相信我可以通过保持列表来关闭ExecutorService Future 对象,然后在所有这些对象上调用 cancel 。但是由于任务是从多个线程提交给这个ExecutorService的,所以没有一种干净的方法可以做到这一点。

I believe I can shutdown the ExecutorService this way by keeping a list of Future objects around and then calling cancel on all of them. But since tasks are being submitted to this ExecutorService from multiple threads, there would not be a clean way to do this.

我真的希望我错过一些明显的东西或者有一种方法可以干净利落地完成。

I'm really hoping I'm missing something obvious or that there's a way to do it cleanly.

感谢您的帮助。

推荐答案

我最近遇到了这个问题。可能有更优雅的方法,但我的解决方案是首先调用 shutdown(),然后拔出 BlockingQueue ThreadPoolExecutor 使用,并在其上调用 clear()(或者将其排放到另一个收藏用于存储)。最后,调用 awaitTermination()允许线程池完成当前的工作。

I ran into this issue recently. There may be a more elegant approach, but my solution is to first call shutdown(), then pull out the BlockingQueue being used by the ThreadPoolExecutor and call clear() on it (or else drain it to another Collection for storage). Finally, calling awaitTermination() allows the thread pool to finish what's currently on its plate.

例如:

public static void shutdownPool(boolean awaitTermination) throws InterruptedException {

    //call shutdown to prevent new tasks from being submitted
    executor.shutdown();

    //get a reference to the Queue
    final BlockingQueue<Runnable> blockingQueue = executor.getQueue();

    //clear the Queue
    blockingQueue.clear();
    //or else copy its contents here with a while loop and remove()

    //wait for active tasks to be completed
    if (awaitTermination) {
        executor.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS);
    }
}

此方法将在包含以下内容的定向类中实现 ThreadPoolExecutor ,引用 executor

This method would be implemented in the directing class wrapping the ThreadPoolExecutor with the reference executor.

重要的是请注意 ThreadPoolExecutor.getQueue() javadoc:

It's important to note the following from the ThreadPoolExecutor.getQueue() javadoc:


访问任务队列主要用于调试和
监视。此队列可能正在使用中。检索任务队列
不会阻止排队任务的执行。

Access to the task queue is intended primarily for debugging and monitoring. This queue may be in active use. Retrieving the task queue does not prevent queued tasks from executing.

这突出显示了可以从其他任务中查询其他任务的事实你消耗它时, BlockingQueue 。但是,根据 BlockingQueue 实现都是线程安全的/concurrent/BlockingQueue.htmlrel =nofollow noreferrer>该界面的文档,所以这不应该导致问题。

This highlights the fact that additional tasks may be polled from the BlockingQueue while you drain it. However, all BlockingQueue implementations are thread-safe according to that interface's documentation, so this shouldn't cause problems.

这篇关于使用Java ExecutorService,如何完成主动执行任务但停止等待任务的处理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆