在ExecutorService上调用shutdown()的原因

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

唯一的(从我收集的)关机,是做一个正常的线程一旦完成。 当正常的线程完成Runnable(或Callable)的运行方法时,它将被传递给垃圾收集器进行收集。 使用Executor服务,线程将被暂时搁置,不会为垃圾收集打勾。 为此,需要关机。

回到我的问题。 有没有任何理由经常调用ExecutorService的closures,甚至在提交给它一些任务之后? 我想留下案件有人正在做这件事,并在此之后,呼吁awaitTermination(),因为这是validation。 一旦我们这样做了,我们不得不重新创build一个新的ExecutorService来做同样的事情。 ExecutorService是不是重复使用线程的想法? 那么为什么要尽快销毁ExecutorService?

是不是一个理性的方式来简单地创buildExecutorService(或者取决于你需要多less个),然后在应用程序运行期间向他们传递任务,然后在应用程序出口或其他重要阶段closures这些任务遗嘱执行人?

我想回答一些使用ExecutorServices编写大量asynchronous代码的经验丰富的编程人员。

第二方面的问题,比较小的处理android平台。 如果你们中的一些人会说,每次closures执行程序并不是最好的想法,并且你在android上编程,你能告诉我,当我们处理不同的事件时,你们如何处理这些closures(具体来说,当你执行它们时)应用生命周期。

由于CommonsWare的评论,我使这个职位保持中立。 我真的没有兴趣争论死亡,似乎是在那里领先。 如果他们愿意分享他们的经验,我只想了解我从有经验的开发人员那里得到的问题。 谢谢。

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

假设您有一个控制台应用程序,它具有执行N个任务的执行程序服务。 如果用户点击CTRL-C,则希望应用程序可能会优雅地终止。 这是什么意思呢? 也许你希望你的应用程序不能够向执行器服务提交更多的任务,同时你想等待你现有的N个任务完成。 作为最后的手段,您可以使用shutdown 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"); } })); 

该钩子将closures服务,这将阻止您的应用程序提交新任务,并在closuresJVM之前等待所有现有任务完成。 等待终止会阻塞5秒,如果服务closures,返回true。 这是在一个循环中完成的,以确保服务最终会closures。 InterruptedException每次都被吞下。 这是closures在您的应用程序中重用的执行程序服务的最佳方法。

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

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

编辑:我想补充一点,我不会build议使用如上所示在一般情况下的关机挂钩:它可能是容易出错,应该是最后的手段而已。 而且,如果你有很多注册的closures钩子,它们运行的​​顺序是不确定的,这可能是不可取的。 我宁愿让应用程序显式调用InterruptedException上的shutdown()

ExecutorService是不是重复使用线程的想法? 那么为什么要尽快销毁ExecutorService?

是。 您不应该经常销毁并重新创buildExecutorService 。 当你需要时(主要是在启动时)初始化ExecutorService并保持活动状态,直到你完成它。

是不是一个理性的方式来简单地创buildExecutorService(或者取决于你需要多less个),然后在应用程序运行期间向他们传递任务,然后在应用程序出口或其他重要阶段closures这些任务遗嘱执行人?

是。 在应用程序退出等重要阶段closuresExecutorService是合理的。

第二方面的问题,比较小的处理android平台。 如果你们中的一些人会说,每次closures执行程序都不是最好的想法,而且你在android上编程,你能告诉我在处理不同的应用程序时如何处理这些closures(具体来说,当你执行它们的时候)生命周期。

假设您的应用程序中的ExecutorService在不同的活动中共享。 每个活动将在不同的时间间隔暂停/恢复,并且您仍然需要为您的应用程序使用一个ExecutorService

而不是pipe理活动生命周期方法中的ExecutorService状态,请将ExecutorServicepipe理(创build/closures)移动到您的自定义服务 。

在Service中创buildExecutorService => onCreate()并在onDestroy()正确closures它

build议closuresExecutorService

如何正确closuresjava的ExecutorService

在ExecutorService上调用shutdown()的原因

今天我遇到了一个情况,那就是在这台机器上开始一系列的任务之前,我必须等待一台机器准备就绪。

我打了一个REST调用这台机器,如果我没有收到503(服务器不可用),那么机器已经准备好处理我的请求。 所以,我等到第一个REST呼叫获得200(成功)。

有多种方式来实现它,我使用ExecutorService来创build一个线程,并安排它在每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开发经验,你很less需要线程。 你正在开发一个游戏或应用程序需要线程的性能? 如果不是的话,在Android中,您可以使用其他方法来解决像上面解释的场景那样的问题。 您可以根据上下文使用TimerTask,AsyncTask或Handlers或Loaders。 这是因为如果UIThread等待很久,你会知道发生了什么:/