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

ExecutorService shutdownNow并没有关闭JVM

吕霄
2023-03-14

我正在学习Java 1.5中引入的ExecutorService

下面的例子似乎违背了预期的行为:

public static void main(String[] args) throws InterruptedException,
ExecutionException,TimeoutException  {
    
    Callable<String> task = () -> {
        int counter = 0;
        while(true) {
            //infinite loop will never exit
            if(counter == 7) {
                break;
            }
        }
        return "abc";
    };
    
    ExecutorService service = Executors.newSingleThreadExecutor();          
    try {
    Future<String> future = service.submit(task);
    
        System.out.println("result = " + future.get(10000,TimeUnit.MILLISECONDS));
    }finally {
        System.out.println("<<<< finally >>>>");
        service.shutdownNow();
    }
    
    
    
}

查看此方法的java文档:

尝试停止所有正在执行的任务,停止正在等待的任务的处理,并返回正在等待执行的任务的列表。

此方法不等待主动执行的任务终止。请使用等待终止来完成此操作。

除了尽最大努力尝试停止处理积极执行的任务之外,没有任何保证。例如,典型的实现将通过Thread.interrupt取消,因此任何未能响应中断的任务都可能永远不会终止。

所以理想情况下,我所期望的是,在指定的超时之后,我会得到一个超时异常,然后ExecutorService将强制关闭,但这不会发生。

查看java文档,它似乎确实表明,无法保证它会关闭。

如果不能保证,那么应该避免吗?

共有1个答案

孙翰墨
2023-03-14

查看java文档,它似乎确实表明,无法保证它会关闭。

对的

如果不能保证,那么应该避免吗?

没有。

你实际上应该做的是以避免或绕过限制的方式使用ExecutorService;例如:

>

  • 执行任何可能长时间运行且应可终止的任务,以便正确处理中断。如果操作正确,您的Executor服务将终止。

    不要依赖于执行器服务的实际关闭。例如,您可以安排在应用程序需要关闭时执行以下操作:

    1. 它调用shutdownNow()
    2. 它调用等待终止(…) 具有适当的超时时间
    3. 如果执行器服务未终止,则调用系统。退出(…)终止应用程序

    配置ExecutorService以将工作线程创建为守护进程线程;请参阅在Java中将ExecutorService转换为守护进程。

    守护进程线程不会阻止JVM退出。但请注意,你需要小心。如果所有非守护进程线程都已完成,JVM将在不中断ExecutorService当前正在运行的任何任务的情况下拔掉插头。

  •  类似资料:
    • 我有以下代码

    • 问题内容: 我一直在对我们的一个宠物项目进行代码审查(通常使用诸如FindBugs之类的工具),并且FindBugs将以下代码标记为错误的(伪代码): 错误是此代码可能不会释放资源。我发现ResultSet和Statement没有关闭,所以我最终将它们关闭: 但是我在许多项目(来自许多公司)中遇到了上述模式,没有人关闭ResultSets或Statements。 关闭连接时,是否关闭了Result

    • 问题内容: 这与“没有单独的联接表的hibernate@OneToMany”类似,因为我需要一个没有联接表的@OneToMany关系。但是,我也不想定义逆关系。删除相反的内容似乎会导致自动生成联接表…是否有解决方法? 问题答案: 在JPA 2.0+中,您可以使用@JoinColumn作为避免生成联接表的方法。 尝试一下。 更新 上面提供的信息摘自EJB 3.0o’illy书(查找@JoinColu

    • 我是Java新手,最近我学习类和对象主题。但是,我无法继续执行此代码: 在主要方法上,我得到了学生的错误,但没有得到老师的错误。我不知道我是否犯了什么错误,或者我看不见。必须做什么? 我得到的错误是: 未使用局部变量学生的值 没有类研究类型的封闭实例是可访问的。必须用类研究类型的封闭实例来限定分配(例如x.newA(),其中x是类研究的实例)。 换行断点:ClassResearch[line: 4

    • 我有一个非常大的异构Python代码库,它使用Django作为前端。这个代码库部署在几个服务器上,这些服务器开始显示出压力,我们正在寻找方法,在重新构建代码库的同时加快速度,并保持新代码的快速运行。 我们目前正在看Pypy,但它似乎有点不确定。它有很多限制,需要重构大量代码(不能用“+”串联字符串?)。

    • 问题内容: 我在运行Jellybean(4.1-4.3)的设备中遇到HttpUrlConnection的一些问题,其中连接未关闭,并且执行多次后导致SocketException“打开的文件过多”。 我确实调用了HttpUrlConnection.disconnect()并在finally块中关闭了所有Inputstream,Outputstream,Reader和Writers。 转到adb s