java - 使用 Java ExecutorService,如何完成主动执行的任务但停止等待任务的处理?

标签 java multithreading

我正在使用 ExecutorService(一个 ThreadPoolExecutor)来运行(和排队)大量任务。我正在尝试编写一些尽可能优雅的关闭代码。

ExecutorService有两种关闭方式:

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

根据 JavaDoc,shutdown 命令:

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.

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

我想调用一个命令:
一个。完成当前 Activity 的任务(如 shutdown)。
b.停止等待任务的处理(如 shutdownNow)。

例如:假设我有一个带有 3 个线程的 ThreadPoolExecutor。目前队列中有 50 个任务,前 3 个正在运行。我想让这 3 个 Activity 任务完成,但我不想让剩余的 47 个任务开始。

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

我真的希望我遗漏了一些明显的东西,或者有一种方法可以干净地做到这一点。

感谢您的帮助。

最佳答案

我最近遇到了这个问题。可能有更优雅的方法,但我的解决方案是先调用shutdown(),然后拉出ThreadPoolExecutor正在使用的BlockingQueue并在其上调用 clear()(或者将其排入另一个 Collection 进行存储)。最后,调用 awaitTermination() 允许线程池完成当前在其盘子上的操作。

例如:

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);
    }
}

此方法将在使用引用 executor 包装 ThreadPoolExecutor 的定向类中实现。

请务必注意 ThreadPoolExecutor.getQueue() 中的以下内容文档:

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 时可能会轮询其他任务。但是,根据 that interface's documentation,所有 BlockingQueue 实现都是线程安全的,所以这应该不会造成问题。

关于java - 使用 Java ExecutorService,如何完成主动执行的任务但停止等待任务的处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8158500/

相关文章:

启动期间 Java 错误 'Unable to create initial connections of pool'

java - 滚动后自定义 ListView 崩溃

java - 当文档不在工作集中时,使用 upsert 和唯一索引原子性进行 MongoDB 更新

multithreading - 如何跨线程共享盒装特征类型的堆分配向量

c++ - 具有非 void 函数的多线程

c - 无锁地将一个值从一个线程传输到另一个线程

java - 如何将项目 Y 添加到项目 X 并将项目 X 添加到项目 Z 并修复问题构建路径

Java输出高于或等于平均分的个数

java线程池和变量参数

java - 多线程环境下迭代集合: ConcurrentModificationException