在过去的几个小时里,我读了很多关于它的文章,但我根本看不出有任何理由(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/
我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
这篇文章是继上一篇文章“Observability:从零开始创建Java微服务并监控它(一)”的续篇。在上一篇文章中,我们讲述了如何创建一个Javaweb应用,并使用Filebeat来收集应用所生成的日志。在今天的文章中,我来详述如何收集应用的指标,使用APM来监控应用并监督web服务的在线情况。源码可以在地址 https://github.com/liu-xiao-guo/java_observability 进行下载。摄入指标指标被视为可以随时更改的时间点值。当前请求的数量可以改变任何毫秒。你可能有1000个请求的峰值,然后一切都回到一个请求。这也意味着这些指标可能不准确,你还想提取最小/
HashMap中为什么引入红黑树,而不是AVL树呢1.概述开始学习这个知识点之前我们需要知道,在JDK1.8以及之前,针对HashMap有什么不同。JDK1.7的时候,HashMap的底层实现是数组+链表JDK1.8的时候,HashMap的底层实现是数组+链表+红黑树我们要思考一个问题,为什么要从链表转为红黑树呢。首先先让我们了解下链表有什么不好???2.链表上述的截图其实就是链表的结构,我们来看下链表的增删改查的时间复杂度增:因为链表不是线性结构,所以每次添加的时候,只需要移动一个节点,所以可以理解为复杂度是N(1)删:算法时间复杂度跟增保持一致查:既然是非线性结构,所以查询某一个节点的时候
遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg
我基本上来自Java背景并且努力理解Ruby中的模运算。(5%3)(-5%3)(5%-3)(-5%-3)Java中的上述操作产生,2个-22个-2但在Ruby中,相同的表达式会产生21个-1-2.Ruby在逻辑上有多擅长这个?模块操作在Ruby中是如何实现的?如果将同一个操作定义为一个web服务,两个服务如何匹配逻辑。 最佳答案 在Java中,模运算的结果与被除数的符号相同。在Ruby中,它与除数的符号相同。remainder()在Ruby中与被除数的符号相同。您可能还想引用modulooperation.
Java的Collections.unmodifiableList和Collections.unmodifiableMap在Ruby标准API中是否有等价物? 最佳答案 使用freeze应用程序接口(interface):Preventsfurthermodificationstoobj.ARuntimeErrorwillberaisedifmodificationisattempted.Thereisnowaytounfreezeafrozenobject.SeealsoObject#frozen?.Thismethodretur
Foo=Class.newFoo.instance_evaldodefinstance_bar"instance_bar"endendputsFoo.instance_bar#=>"instance_bar"putsFoo.new.instance_bar#=>undefinedmethod‘instance_bar’我的理解是调用instance_eval在对象上应该允许您为该对象定义实例变量或方法。但是在上面的例子中,当你在类Foo上调用它来定义instance_bar方法时,instance_bar变成了一个可以用“Foo.instance_bar”调用的类方法。很明显这段代码没