当前位置: 首页 > 知识库问答 >
问题:

如何在不丢失任务的情况下关闭和重新实例化执行者服务

董奇思
2023-03-14

我不完全理解,我应该如何在偶尔即将到来的任务的应用程序中实现ExecutorService。每项任务运行约15分钟(长20倍)。有时一天有10个任务,有时一整周都没有。

因此,在执行了一些任务之后,如果队列中没有剩余的任务,我想关闭执行器,因为它不再需要了,这样垃圾收集器就可以继续它的工作。调用shutdown后,没有新任务排队等待执行器。

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

这是我的方法:

// 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,我将初始化一个新的执行器,到目前为止一切正常。否则,如果执行器当前正在终止(因为调用了shutdown),则执行器不会接受进一步的任务。所以我等到它被终止,然后初始化一个新的。之后我提交我的任务。。。我只在队列中没有其他任务时关闭执行器。尽管我等了一个小时,因为可能还有一个正在运行的任务。

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

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

提前感谢。

共有1个答案

蒙峰
2023-03-14

我想关闭执行器,因为它不再需要了,这样垃圾收集器就可以工作了。

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

我读到只有在我关闭执行器时才会调用垃圾收集器。

你要么记错了,要么读到了不好的信息。

因为您使用的是单个线程,所以实际上不需要担心池的配置。一个长寿命的执行者。新固定线程池(1) 就是你所需要的。

如果确实需要释放资源,可以使用新的ThreadPoolExecutor(0,1,30,TimeUnit.SECONDS,new LinkedBlockingQueue)之类的工具来配置核心池大小

 类似资料:
  • 问题内容: 我不能使用,因为有可能在等待时将新任务添加到ThreadPoolExecutor中。 因此,我正在寻找一种方法,等待ThreadPoolExecutor清空队列并完成所有任务,而又不阻止在此之前添加新任务。 如果有什么不同,这适用于Android。 谢谢 更新 :几周后,我再次进行了修改,发现在这种情况下,修改后的CountDownLatch对我而言效果更好。我会保留答案,因为它更适用

  • 网上有不少关于这个错误的帖子。我的情况是,我有时可以建立连接,但大多数时候失败了。以下是失败时的错误: 以下是成功时的信息: 我没有很好的解释,为什么有时它能工作,而另一次却不能。在每次之前,Mate 9上启用了

  • 问题内容: 我可以重新加载当前页面而不丢失任何表单数据吗?我用了.. 和 但是这两件事对我来说无法获得早期的表格数据。怎么了 ?手动刷新浏览器时,一切正常(我不会丢失任何表单数据)。请指导我如何解决。 这是我的完整代码… 并在我的JS文件中。 问题答案: 您可以使用各种本地存储机制在浏览器中存储此数据,例如Web Storage,IndexedDB,WebSQL(不建议使用)和File API(不

  • 我正在编程服务,从数据库中获取数据,并通过REST服务提供这些数据。它使用spring mvc。我的数据库连接配置在属性文件中,在上下文初始化期间,spring将其作为数据源bean从中加载。 现在我的问题是-我想更改属性文件中的配置(例如更改数据库信息),但我无法重新启动应用程序服务器,因此无法加载新配置。 如何重新初始化Spring上下文或一些特定的bean,以便使用新定义的属性?

  • 编辑问题,以包括预期行为、特定问题或错误以及重现问题所需的最短代码。这将有助于其他人回答问题。 哪里出错:< br >任务执行失败”:app:checkDevDebugAarMetadata。 无法解析配置': app: devDebugRuntime Classpath'的所有文件。无法解析net.minidev: json-Smart:[1.3.1,2.3]。需要:项目:app 我在构建项目时

  • 我正在尝试将ChromeOptions传递给我的驱动程序以允许弹出窗口。我将TestNG与@BeforeClass、@Test和@AfterClass注释一起使用。。我正在尝试启用弹出窗口,并且使用以下方法成功地实现了这一点。 虽然这确实有效,但它会打开webdriver,然后打开另一个带有选项的驱动程序。我不希望出现两个Web驱动程序。。我只想把这些选项传递给第一个webdriver!我使用一个