[英]Reason for calling shutdown() on ExecutorService
在过去的几个小时里,我读了很多关于它的内容,我根本看不出有任何理由(正当理由)在ExecutorService
上调用shutdown()
,除非我们有一个庞大的应用程序来存储数十个不同的 executor长时间不使用的服务。
关闭所做的唯一一件事(从我收集到的)就是执行正常线程完成后所做的事情。 当普通Thread执行完Runnable(或Callable)的run方法后,会传递给Garbage Collection进行回收。 使用 Executor Service 线程将被简单地搁置,它们不会被垃圾收集勾选。 为此,需要关机。
好的回到我的问题。 是否有任何理由经常在ExecutorService
上调用关闭,甚至在向其提交某些任务后立即调用? 我想留下有人正在做的情况,然后在调用awaitTermination()
之后awaitTermination()
进行验证。 一旦我们这样做了,我们必须重新创建一个新的ExecutorService
来做同样的事情。 ExecutorService
重用线程的全部想法不是吗? 那么为什么要这么快销毁ExecutorService
呢?
简单地创建ExecutorService
(或根据您需要的数量而定),然后在应用程序运行期间将任务传递给他们,然后在应用程序退出或其他一些重要阶段关闭那些执行人?
我想要一些有经验的编码人员的答案,他们确实使用 ExecutorServices 编写了大量异步代码。
第二个方面的问题,与 android 平台的交易有点小。 如果你们中的一些人会说每次关闭执行程序并不是最好的主意,以及你在 android 上的程序,你能告诉我当我们处理不同的事件时你如何处理这些关闭(具体来说 - 当你执行它们时)应用程序生命周期。
由于 CommonsWare 的评论,我使帖子中立。 我真的没有兴趣把它争论到死,而且它似乎正在领先。 我只对了解我在这里向有经验的开发人员询问的内容感兴趣,他们是否愿意分享他们的经验。 谢谢。
shutdown()
方法做一件事:阻止客户端向执行程序服务发送更多工作。 这意味着除非采取其他操作,否则所有现有任务仍将运行完成。 即使对于计划任务也是如此,例如,对于 ScheduledExecutorService:计划任务的新实例不会运行。 它还释放任何后台线程资源。 这在各种情况下都很有用。
假设您有一个控制台应用程序,它有一个运行 N 个任务的执行程序服务。 如果用户按下 CTRL-C,您希望应用程序终止,可能会正常终止。 优雅地是什么意思? 也许您希望您的应用程序无法向执行程序服务提交更多任务,同时您希望等待您现有的 N 个任务完成。 您可以使用关闭挂钩作为最后的手段来实现这一点:
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");
}
}));
这个钩子将关闭服务,这将阻止您的应用程序提交新任务,并在关闭 JVM 之前等待所有现有任务完成。 如果服务关闭,等待终止将阻塞 5 秒并返回 true。 这是在循环中完成的,以便您确定服务最终会关闭。 InterruptedException 每次都会被吞下。 这是关闭在整个应用程序中重复使用的执行程序服务的最佳方法。
这段代码并不完美。 除非您绝对肯定您的任务最终会终止,否则您可能希望等待给定的超时时间,然后退出,放弃正在运行的线程。 在这种情况下,在最后一次尝试中断正在运行的线程时在超时后调用shutdownNow()
也是有意义的( shutdownNow()
还会为您提供等待运行的任务列表)。 如果您的任务旨在响应中断,这将正常工作。
另一个有趣的场景是当您有一个执行周期性任务的 ScheduledExecutorService 时。 停止周期性任务链的唯一方法是调用shutdown()
。
编辑:我想补充一点,我不建议在一般情况下使用如上所示的关闭钩子:它可能容易出错,并且应该只是最后的手段。 此外,如果您注册了许多关闭挂钩,则它们运行的顺序是未定义的,这可能是不可取的。 我宁愿让应用程序在InterruptedException
上显式调用shutdown()
。
ExecutorService 重用线程的全部想法不是吗? 那么为什么要这么快销毁 ExecutorService 呢?
是的。 您不应该频繁地销毁和重新创建ExecutorService
。 在您需要时(主要是在启动时)初始化ExecutorService
并使其保持活动状态,直到您完成它。
简单地创建 ExecutorService(或根据您需要的数量而定),然后在应用程序运行期间将任务传递给他们,然后在应用程序退出或其他一些重要阶段关闭那些执行人?
是的。 在应用程序退出等重要阶段关闭ExecutorService
是合理的。
第二个方面的问题,与 android 平台的交易有点小。 如果你们中的一些人会说每次关闭执行程序并不是最好的主意,并且你在 android 上编程,你能告诉我当我们处理应用程序的不同事件时你如何处理这些关闭(具体来说,当你执行它们时)生命周期。
假设ExecutorService
在您的应用程序中的不同活动之间共享。 每个活动将在不同的时间间隔暂停/恢复,但每个应用程序仍然需要一个ExecutorService
。
不是在 Activity 生命周期方法中管理ExecutorService
的状态,而是将 ExecutorService 管理(创建/关闭)移动到您的自定义Service 。
在 Service => onCreate()
创建ExecutorService
并在onDestroy()
正确关闭它
关闭ExecutorService
推荐方式:
一旦不再需要 ExecutorService 以释放系统资源并允许正常关闭应用程序,就应该关闭它。 因为 ExecutorService 中的线程可能是非守护线程,它们可能会阻止正常的应用程序终止。 换句话说,您的应用程序在完成其 main 方法后保持运行。
第14话页数:814
在 ExecutorService 上调用 shutdown() 的原因
今天我遇到了一种情况,我必须等到一台机器准备就绪,然后才能在该机器上启动一系列任务。
我对这台机器进行 REST 调用,如果我没有收到 503(服务器不可用),那么该机器已准备好处理我的请求。 所以,我等到第一个 REST 调用得到 200(成功)。
有多种方法可以实现它,我使用 ExecutorService 创建一个线程并安排它在每 X 秒后运行一次。 所以,我需要在某个条件下停止这个线程,看看这个......
final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
Runnable task = () -> {
try {
int statusCode = restHelper.firstRESTCall();
if (statusCode == 200) {
executor.shutdown();
}
} catch (Exception e) {
e.printStackTrace();
}
};
int retryAfter = 60;
executor.scheduleAtFixedRate(task, 0, retryAfter, TimeUnit.SECONDS);
第二个方面的问题,与 android 平台的交易有点小。
如果您提供更多背景信息,也许我可以回答! 此外,根据我在 Android 开发方面的经验,您很少需要 Threads。 您是否正在开发需要线程以提高性能的游戏或应用程序? 如果没有,在 Android 中,您有其他方法来解决问题,例如我上面解释的场景。 您可以根据上下文使用 TimerTask、AsyncTask 或处理程序或加载程序。 这是因为如果 UIThread 等待很长时间你知道会发生什么:/
尽管对于计划的任务,例如,对于 ScheduledExecutorService,这是真实的:预定分配的新案例将不会运行。
我们应该期望你有一个舒适的应用程序,它有一个运行 N 个差事的代理管理。
我没有毫不费力地抓住它的意思? 也许您需要您的应用程序无法选择向代理管理部门提交更多任务,同时您需要坐下来完成当前的 N 项任务。
除非你完全肯定你的差事最终会完成,否则你应该需要坐下来休息一段时间,然后简单地退出,抛弃正在运行的字符串。
如果您的活动旨在对干扰做出反应,这将正常工作。
另一个有趣的情况是您有一个 ScheduledExecutorService 来执行活动。
停止活动链的最好方法是调用 shutdown()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.