【问题标题】:Why ThreadPoolExecutor finalize invokes shutdown and not shutdownNow为什么 ThreadPoolExecutor finalize 调用shutdown而不是shutdownNow
【发布时间】:2012-09-23 00:21:59
【问题描述】:

ThreadPoolExecutor 中的Finalize 方法如下所示。

protected void finalize()  {
    shutdown();
}

考虑下面的程序,其中线程永远不会终止

ExecutorService executorService = Executors.newSingleThreadExecutor();
    executorService.submit(new Runnable() {
        @Override
        public void run() {
            try {
                new SynchronousQueue<String>()
                        .put("will never get removed");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    });
    executorService = null;
    System.gc();

}

在这种情况下,shutdownNow 会是比shutdown 更好的选择,至少 JVM 在这种情况下可以退出。

更新:

对于finalize 调用shutdown 方法的唯一可能解释是,如果程序员没有显式调用它,它将在GC 作为防御机制时被调用。我发现这种机制存在缺陷,因为在上述情况下 JVM 不会被终止。

【问题讨论】:

    标签: java executorservice


    【解决方案1】:

    首先,让我问你一个问题:为什么需要池化一个永不终止的线程?您汇集对象以重用它们。

    java之所以调用shutdown,是为了给线程一个优雅终止的机会。

    如果你需要在一个无限循环中运行一个线程,那么你的线程应该检查Thread.currentThread().isInterrupted()返回false,然后从run()返回。

    在您展示的示例中,您可能希望使用带有超时的方法offer(),而不是put()

    最坏的情况,您可以扩展ThreadPoolExecutor 并在终结器中调用shutdownNow()

    【讨论】:

    • 更新了问题。问题是它是否是防御机制,为什么要以这种方式实施?
    • 这并不是一个真正的防御机制,所以ThreadPoolExecutor 的行为就像任何其他 java 对象一样,当它无法访问时,它会告诉线程停止以便它可以被垃圾收集。跨度>
    【解决方案2】:

    这个故事的寓意是,如果你想关闭一个线程池,你不应该依赖 finalize 来完成它。对于 Java 中的任何资源都是如此,您应该从不依赖于终结机制(因为它可能运行)。如果你想关闭一个线程池,你应该自己管理它。

    finalize 方法中的shutdown() 调用是一个合理的折衷方案,以防程序员“意外”失去对线程池的跟踪。当前任务将运行完成,然后池将关闭。如果使用shutdownNow(),在某个随机时间点(取决于 gc),您的任务将被中断。可能不太理想。而且,您可以始终创建一个拒绝关闭的任务,无论是否调用了 shutdown()shutdownNow()(只需在示例中的 try/catch 块周围添加一个 while(true) 循环)。

    【讨论】:

      【解决方案3】:

      shutdown() 被调用时,这意味着池不会接受新的任务,并且在提交的任务完成后实际上会“关闭”。对于您的情况,您最好在您想要的地方显式调用shutdownNow()

      【讨论】:

        猜你喜欢
        • 2014-04-28
        • 2011-12-08
        • 1970-01-01
        • 2013-11-21
        • 1970-01-01
        • 2012-07-16
        • 2021-10-18
        • 2014-08-09
        • 1970-01-01
        相关资源
        最近更新 更多