如何在不丢失任务的情况下关闭和实例化 Executorservice

How to shutdown and reinstantiate an Executor Service without loosing tasks

我不完全明白,我应该如何在偶尔有即将到来的任务的应用程序中实现 ExecutorService。每个任务运行大约 15 分钟(有时更长)。有时一天有 10 个任务,有时整个星期 none。

因此,如果队列中没有剩余任务,则在执行一些任务后,我想关闭执行程序,因为它不再需要,以便垃圾收集器可以完成它的工作。 调用 shutdown 后,没有新任务排队到执行器。

现在,我的问题是我必须确保所有任务都已完成。这意味着,在调用 shutdown 之后,我必须确保在提交新任务之前实例化了一个新的 Executor Service。我必须等到旧的执行器服务关闭(或终止?)并启动一个新的。我应该如何实施?

这是我的方法:

// sync block to check for each task if a new Executor Service has to be created before submitting the task
synchronized (this) {
    // do I have to check both isSutdown and isTerminated?
    if (null == businessTaskExecutor || businessTaskExecutor.isShutdown() || businessTaskExecutor.isTerminated()) {
        // simply init a new one
        businessTaskExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
    } else if (businessTaskExecutor.isTerminating()) {
        // the termination process has started and is not done.
        // Do I have to wait for the old executor or can I simply init a new one without waiting?
        while (!businessTaskExecutor.isTerminated()) { }
        businessTaskExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(1);
    }
}
Future<?> future = businessTaskExecutor.submit(() -> new BusinessTaskRunnable(businessTask));
if (future.isDone() && businessTaskExecutor.getQueue().isEmpty()) {
    businessTaskExecutor.shutdown();
    try {
        if (!businessTaskExecutor.awaitTermination(1, TimeUnit.HOURS)) {
            businessTaskExecutor.shutdownNow();
        }
    } catch (InterruptedException ex) {
        businessTaskExecutor.shutdownNow();
        Thread.currentThread().interrupt();
    }
}

解释:

如果执行者是null/shutdown/terminated,我会初始化一个新的,到目前为止一切顺利。 否则,如果执行程序当前正在终止(因为调用了关闭),则执行程序将不会接受进一步的任务。所以我等到它终止,然后启动一个新的。 之后我提交我的任务...... 如果队列中没有其他任务,我只会关闭执行程序。尽管我等了一个小时,因为仍然可能有 运行 任务。

是否有更好的实现我希望的行为?

附加信息:我使用 ThreadPoolExecutor,因为我需要 getQueue() 检查它是否为空。我还可以在不同的实现中使用任何其他类型的执行器服务。

提前致谢。

I want to shutdown the executor as it is not needed anymore and so that the garbage collector can to its job.

但是 需要它,这就是您要重新创建它的原因。无论执行程序是否关闭,GC 都可以完成它的工作(除非你设法创建了一些非常特殊的东西,例如 ThreadLocal 会以某种方式将对象绑定到执行程序)。

I read that the garbage collector will only be invoked if I shut the executor down.

你要么记错了,要么阅读了错误的信息。

由于您是 运行 单线程,因此您实际上什至不需要担心池配置。一个长寿的Executors.newFixedThreadPool(1);就是你所需要的。

如果您确实需要释放资源,您可以使用类似 new ThreadPoolExecutor(0, 1, 30, TimeUnit.SECONDS, new LinkedBlockingQueue<BusinessTaskRunnable>()); 的配置 core pool size。但这是无关紧要的微优化,一个线程不应该有所作为。