Java 为什么ThreadPoolExecutor finalize调用shutdown而不是shutdownNow

Java 为什么ThreadPoolExecutor finalize调用shutdown而不是shutdownNow,java,executorservice,Java,Executorservice,类ThreadPoolExecutor中的Finalize方法如下所示 protected void finalize() { shutdown(); } 考虑下面的程序,其中线程从不终止 ExecutorService executorService = Executors.newSingleThreadExecutor(); executorService.submit(new Runnable() { @Override public v

类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();

}
在这种情况下,ShutdowNow比ShutdowNow更好,至少JVM在这种情况下可以退出

更新:


关于finalize调用shutdown方法的唯一可能解释是,若程序员并没有显式调用它,它将在GC作为防御机制时被调用。我看到了这个机制中的缺陷,因为在上述情况下,JVM不会被终止。

首先,让我问你一个问题:为什么需要将一个从未终止的线程集中在一起?您可以将对象合并以重用它们

java调用shutdown的原因是给线程一个优雅地终止的机会

如果需要在无限循环中运行线程,那么线程应该检查thread.currentThread.isInterrupted returs false,然后从运行返回

在您展示的示例中,您可能希望将方法offer与超时一起使用,而不是与put一起使用


在第一种情况下,您可以扩展ThreadPoolExecutor并在终结器中调用shutdownNow。

首先,让我问您一个问题:为什么需要将一个永不终止的线程汇集在一起?您可以将对象合并以重用它们

java调用shutdown的原因是给线程一个优雅地终止的机会

如果需要在无限循环中运行线程,那么线程应该检查thread.currentThread.isInterrupted returs false,然后从运行返回

在您展示的示例中,您可能希望将方法offer与超时一起使用,而不是与put一起使用


在第一种情况下,您可以扩展ThreadPoolExecutor并在终结器中调用shutdownNow。

调用shutdown时,表示池将不接受新任务,并在提交的任务完成后实际关闭。对于您的情况,最好在您想要的地方显式地调用shutdownNow

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

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


finalize方法中的shutdown调用是程序员意外丢失线程池跟踪的合理折衷方法。当前任务将运行到完成,然后池将关闭。如果使用SHUTDOWNOW,根据gc在某个随机时间点,您的任务将被中断。可能不太理想。而且,您始终可以创建一个拒绝关闭的任务,无论调用的是shutdown还是shutdownNow,只要在示例中的try/catch块周围添加whiletrue循环即可。

这个故事的寓意是,如果您希望关闭线程池,就不应该依赖finalize来完成它。Java中的任何资源都是如此,您永远不应该依赖于终结机制,因为它可能永远不会运行。如果希望线程池关闭,则应自行管理


finalize方法中的shutdown调用是程序员意外丢失线程池跟踪的合理折衷方法。当前任务将运行到完成,然后池将关闭。如果使用SHUTDOWNOW,根据gc在某个随机时间点,您的任务将被中断。可能不太理想。而且,您始终可以创建一个拒绝关闭的任务,无论调用的是shutdown还是shutdownNow,只要在示例中的try/catch块周围添加whiletrue循环即可。

更新了问题。问题是,如果它是防御机制,为什么它会以这种方式实现?它不是真正的防御机制,所以ThreadPoolExecutor的行为会像任何其他java对象一样,当它无法访问时,它会告诉线程停止,以便它可以被垃圾收集。更新了问题。问题是,它是否是一种防御机制,为什么会以这种方式实现?它不是一种真正的防御机制,所以ThreadPoolExecutor的行为会像任何其他java对象一样,当它无法访问时,它会告诉线程停止,以便可以对其进行垃圾收集。