- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
在过去的几个小时里,我读了很多关于它的文章,但我根本看不出有任何理由(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/
我对cassandra并使用1.2.10非常陌生。我有一个时间戳数据类型的主键列。现在,我正在尝试检索日期范围的数据。由于我们知道不能在cassandra中使用,因此我使用的是大于()来获取日期范围。
我正在尝试进行有条件的转场。但我得到: Terminating app due to uncaught exception 'NSInvalidArgumentException', reas
我有一个游戏项目,在调试和发布模式下在设备上运行得非常好。我有两个版本。旧版本和新版本具有更多(后来我添加了)功能,并且两者的 bundle ID、版本相同。当我构建旧版本时,之前没有安装“myGam
这个问题已经有答案了: 奥 git _a (2 个回答) 已关闭 5 年前。 我正在获取 ClassCastException 。这两个类来自不同的 jar,但是JettyContinuationPr
以下代码行抛出异常: HttpResponse response = client.execute(request); // actual HTTP request 我能够捕获它并打印: Log
就目前情况而言,这个问题不太适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、民意调查或扩展讨论。如果您觉得这个问题可以改进并可能重新开放,visit
public class TwoThreads { private static Object resource = new Object(); private static void
当我输入 6 (int) 作为值时,运行此命令会出现段错误 (gcc filename.c -lm)。请帮助我解决这个问题。预期的功能尚未实现,但我需要知道为什么我已经陷入段错误。 谢谢! #incl
所以,过去一周半我一直在研究这个 .OBJ/.MTL 网格解析器。在这段时间里,我一直在追踪/修复很多错误、清理代码、记录代码等等。 问题是,每修复一个错误,仍然会出现这个问题,而且一张图片胜过一千个
我正在运行一个代码,它基本上围绕 3 个维度旋转一个大数据数组(5000 万行)。但是,我遇到了一个奇怪的问题,我已将其缩小到如何评估旋转矩阵。基本上,对于除绕 x 轴以外的任何旋转,python 代
就在你说这是重复之前,我已经看到了其他问题,但我仍然想发布这个。 所以我正在阅读 Thinking in Java -Bruce Eckel 这篇文章是关于小写命名约定的: In Java 1.0 a
我想在我的应用程序中使用 REST API。它为我从这个应用程序发出的所有请求抛出 SocketTimeoutException。 Logcat 输出:(您也可以在此处看到带有漂亮格式的输出:http
我知道 raise ... from None 并已阅读 How can I more easily suppress previous exceptions when I raise my own
在未能找到各种Unix工具(例如xargs和whatnot)的最新独立二进制文件(this version很好,但需要外部DLL)后,我承担了自己进行编译的挑战。 ...这是痛苦的。 最终,尽管如此,
我有一个用PHP编写的流套接字服务器。 为了查看一次可以处理多少个连接,我用C语言编写了一个模拟器来创建1000个不同的客户端以连接到服务器。 stream_socket_accept几次返回fals
我的Android Studio昨天运行良好,但是今天当我启动Android Studio并想在移动设备上运行应用程序时,发生了以下错误, 我在互联网和stackoverflow上进行了搜索,但没有解
默认情况下,grails似乎为Java域对象的toString()返回:。那当然不是我想要的,所以我尝试@Override toString()返回我想要的。当我尝试grails generate-a
尝试通过LDAP通过LDAP对用户进行身份验证时,出现以下错误。 Reason: Cannot pass null or empty values to constructor. 谁能告诉我做错了什么
我正在尝试使用应用程序附带的 Houdini Python 模块,该模块是 Houdini 安装文件夹的一部分,位于标准 Python 路径之外。按照安装说明操作后,运行 Houdini Termin
简单地说,我正在为基本数据库编写单链表的原始实现。当用户请求打印索引下列出的元素高于数据库中当前记录数量时,我不断出现段错误,但仅当差值为 1 时。对于更高的数字,它只会触发我在那里编写的错误系统。
我是一名优秀的程序员,十分优秀!