gpt4 book ai didi

java - 在 ExecutorService 上调用 shutdown() 的原因

转载 作者:IT老高 更新时间:2023-10-28 13:14:49 24 4
gpt4 key购买 nike

在过去的几个小时里,我读了很多关于它的文章,但我根本看不出有任何理由(valid 理由)调用 shutdown() ExecutorService,除非我们有一个庞大的应用程序来存储几十个很长时间不使用的不同的执行器服务。

唯一的事情(据我所知)关闭所做的就是做一个普通线程在完成后所做的事情。当普通的 Thread 完成 Runnable(或 Callable)的 run 方法后,会被传递给 Garbage Collection 进行收集。使用 Executor Service,线程将被搁置,不会为垃圾收集打勾。为此,需要关机。

好的,回到我的问题。是否有任何理由经常在 ExecutorService 上调用关闭,甚至在提交一些任务之后立即调用它?我想留下有人正在这样做的情况,然后在调用 awaitTermination() 之后立即进行验证,因为这是经过验证的。一旦我们这样做了,我们必须重新创建一个新的 ExecutorService 来做同样的事情。 ExecutorService 的全部想法不就是重用线程吗?那么为什么这么快就销毁ExecutorService呢?

简单地创建 ExecutorService (或根据您需要多少),然后在应用程序运行期间将任务传递给它们,然后再传递给它们,这不是一种合理的方式吗?应用程序退出或其他一些重要阶段关闭这些执行器?

我想从一些使用 ExecutorServices 编写大量异步代码的经验丰富的程序员那里得到答案。

第二个问题,与 android 平台有关的小一点的交易。如果你们中的一些人会说每次都关闭执行程序并不是最好的主意,并且你的程序在 android 上,你能告诉我当我们处理不同的事件时你如何处理这些关闭(具体来说 - 当你执行它们时)应用程序生命周期。

由于 CommonsWare 评论,我将帖子设为中立。我真的没有兴趣争论到死,而且似乎它正在导致那里。我只对了解我在这里向经验丰富的开发人员提出的问题感兴趣,他们是否愿意分享他们的经验。谢谢。

最佳答案

shutdown() 方法做了一件事:阻止客户端向执行器服务发送更多工作。这意味着除非采取其他行动,否则所有现有任务仍将运行完成。即使对于计划任务也是如此,例如,对于 ScheduledExecutorService:计划任务的新实例不会运行。它还释放任何后台线程资源。这在各种情况下都很有用。

假设您有一个控制台应用程序,它有一个执行器服务运行 N 个任务。如果用户按下 CTRL-C,您希望应用程序终止,可能是正常的。优雅是什么意思?也许您希望您的应用程序无法向执行器服务提交更多任务,同时您希望等待现有的 N 个任务完成。作为最后的手段,您可以使用关闭 Hook 来实现此目的:

final ExecutorService service = ... // get it somewhere

Runtime.getRuntime().addShutdownHook(new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Performing some shutdown cleanup...");
service.shutdown();
while (true) {
try {
System.out.println("Waiting for the service to terminate...");
if (service.awaitTermination(5, TimeUnit.SECONDS)) {
break;
}
} catch (InterruptedException e) {
}
}
System.out.println("Done cleaning");
}
}));

此钩子(Hook)将关闭服务,这将阻止您的应用程序提交新任务,并在关闭 JVM 之前等待所有现有任务完成。 await 终止将阻塞 5 秒,如果服务关闭则返回 true。这是在循环中完成的,因此您确定服务最终会关闭。 InterruptedException 每次都被吞没。这是关闭在整个应用程序中重用的执行程序服务的最佳方法。

这段代码并不完美。除非您绝对肯定您的任务最终会终止,否则您可能希望等待给定的超时时间然后退出,放弃正在运行的线程。在这种情况下,在超时后也调用 shutdownNow() 以最终尝试中断正在运行的线程是有意义的(shutdownNow() 也会给你一个列表等待运行的任务)。如果您的任务旨在响应中断,这将正常工作。

另一个有趣的场景是当您有一个 ScheduledExecutorService 执行周期性任务时。停止周期性任务链的唯一方法是调用 shutdown()

编辑:我想补充一点,我不建议在一般情况下使用如上所示的关闭 Hook :它可能容易出错,并且只能作为最后的手段。此外,如果您注册了许多关闭 Hook ,则它们的运行顺序是未定义的,这可能是不可取的。我宁愿让应用程序在 InterruptedException 上显式调用 shutdown()

关于java - 在 ExecutorService 上调用 shutdown() 的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16122987/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com