当前位置: 首页 > 知识库问答 >
问题:

对ExecutorService调用shutdown()的原因

易昌翰
2023-03-14

在过去的几个小时里,我读了很多关于它的文章,我根本看不到任何在executorService上调用shutdown()的理由(有效的理由),除非我们有一个庞大的应用程序,它存储了几十个不同的执行器服务,而这些服务并不是长期使用的。

关机所做的唯一事情(据我所知)是在正常的线程完成之后做它所做的事情。当正常线程将完成Runnable(或Callable)的run方法时,它将被传递到垃圾回收以进行收集。使用Executor服务,线程将被简单地搁置,它们不会被勾选进行垃圾回收。为此需要关闭。

好,回到我的问题。有没有理由经常对executorservice调用shutdown,甚至在向其提交某些任务之后调用shutdown?我想留下这样一个例子:有人在做这件事,然后在验证这件事时调用awaittermination()。一旦这样做,我们必须重新创建一个新的executorservice,以完成同样的任务。executorservice的全部思想不就是重用线程吗?那么为什么这么快就销毁executorservice呢?

简单地创建executorservice(或者根据需要的数量进行耦合),然后在应用程序运行期间将任务传递给它们,然后在应用程序退出或其他重要阶段关闭这些执行程序,这难道不是一种合理的方法吗?

我想从一些有经验的程序员那里得到答案,他们确实使用ExecutorServices编写了大量的异步代码。

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

由于CommonsWare的评论,我使帖子中立。我真的没有兴趣争论到死,它似乎是导致了那里。我只想从有经验的开发人员那里了解我在这里询问的内容,如果他们愿意分享他们的经验的话。多谢了。

共有1个答案

暨正真
2023-03-14

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

让我们假设您有一个控制台应用程序,它有一个运行N个任务的executor服务。如果用户点击CTRL-C,您希望应用程序终止,可能会很优雅地终止。优雅是什么意思?也许您希望您的应用程序不能向executor服务提交更多的任务,同时您希望等待您现有的N个任务完成。您可以使用shutdown挂钩作为最后的手段来实现这一点:

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。await终止将阻塞5秒,如果服务关闭,则返回true。这是在一个循环中完成的,这样您就可以确定服务最终会关闭。InterruptedException每次都会被吞噬。这是关闭在应用程序中重用的executor服务的最佳方法。

这个代码并不完美。除非您完全肯定您的任务最终会终止,否则您可能希望等待给定的超时,然后退出,放弃正在运行的线程。在这种情况下,在最后尝试中断正在运行的线程时,在超时之后调用ShutdownNow()也是有意义的(ShutdownNow()还会给出等待运行的任务列表)。如果您的任务被设计为响应中断,这将很好地工作。

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

编辑:我想补充一点,我不建议在一般情况下使用如上所示的关机挂钩:它可能容易出错,并且应该是最后的手段。此外,如果您注册了许多关机钩子,则它们的运行顺序未定义,这可能是不希望的。我希望应用程序在interruptedexception上显式调用shutdown()

 类似资料:
  • 问题内容: 我有一个代码,其中4个线程同时运行。我想等到所有这4个线程都结束。并且只有在那之后才能继续应用程序流程。 我尝试了两种方法: ,这种方法可以正常工作。之后的代码仅在所有线程完成后才执行。 ,此技术允许执行代码,即使并非所有线程都已完成,也可以执行代码。 代码示例: 我的问题: 为什么并且不要等到所有线程都完成并打印出来 _«我们完成了! 所有线程都完成了!» _刚打完电话? 问题答案:

  • 我有一个4个线程同时运行的代码。我想等到所有这4个线程都完成。并且只有在那之后才能继续应用程序流程。 我尝试了两种方法: ,此方法按预期工作。 之后出现的代码仅在所有线程完成后执行。 ,这种技术允许执行代码,即使不是所有线程都已完成,也会在 之后执行。 代码示例: 我的问题: 为什么 和 不要等到所有线程都完成并打印 “我们完成了!所有线程都已完成!» 在调用 ?

  • 我是我的代码,我向ExecutorService提交一些任务,然后使用shutdown()和awaitTermination()等待它们完成。但是,如果任何一个任务需要超过一个特定的时间来完成,我希望它被取消,而不影响其他任务。我使用来自ExecutorService的代码修正代码,该代码在超时后中断任务,如下所示: 以及任务何时有时间完成和何时不能同时工作的测试案例 并且在我的代码中似乎起作用:

  • 关闭、重启或注销系统。 Shutdown, Code 参数 Code 在下面列出的关闭代码的组合. 备注 关闭代码包含下列值: logoff 0 Shutdown 1 重启 2 强制 4 断电 8 挂起/休眠 请参阅本页底部的 DllCall 示例. 关闭显示器 请参阅 PostMessage 示例。 把需要的值加在一起. 例如, 要关闭并切断电源的代码为 9 (关闭 + 切断电源 = 1 + 8

  • 描述 (Description) 此函数根据HOW的值禁用套接字连接。 HOW的有效值与同名的系统调用相同。 值为0表示您已停止从套接字读取信息。 值为1表示您已停止写入套接字。 值为2表示您已完全停止使用套接字。 语法 (Syntax) 以下是此函数的简单语法 - shutdown SOCKET, HOW 返回值 (Return Value) 此函数在失败时返回0,在成功时返回1。<!-- 例

  • shutdown(终止socket通信) 相关函数 socket,connect 表头文件 #include<sys/socket.h> 定义函数 int shutdown(int s,int how); 函数说明 shutdown()用来终止参数s所指定的socket连线。参数s是连线中的 socket处理代码,参数how有下列几种情况: how=0 终止读取操作。 how=1 终止传送操作 h