当前位置: 首页 > 面试题库 >

为什么此线程池未收集到垃圾?

胡元明
2023-03-14
问题内容

在此代码示例中,ExecutorService仅用于其中一个,并允许其超出范围。

public static void main(String[] args)
{
    ExecutorService executorService = Executors.newFixedThreadPool(3);
    executorService.submit(new Runnable()
    {
        public void run()
        {
            System.out.println("hello");
        }
    });
}

一旦executorService超出范围,就应该对其进行收集和完成。ThreadPoolExecutor中的finalize()方法调用shutdown()。

/**
 * Invokes {@code shutdown} when this executor is no longer
 * referenced and it has no threads.
 */
protected void finalize() {
    shutdown();
}

调用shutdown()后,池线程应终止,并且应允许JVM退出。但是,永远不会收集executorSerivce,因此JVM仍保持活动状态。甚至对System.gc()的调用似乎也不起作用。为什么即使main()终止后,executorService也没有被收集?

注意:我知道我应该自己调用shutdown(),而且我总是在测试之外进行。我很好奇为什么终结处理在这里不能作为备份。


问题答案:

尽管这没有帮助,但这与GC的不确定性没有任何关系!(这是您的示例中的一个原因,但是即使我们“修复”了它以消耗内存并强制执行一个集合,它仍然不会最终确定)

执行者创建的Worker线程是内部类,它们具有对执行者本身的引用。(他们需要它能够看到队列,运行状态等!)正在运行的线程不会被垃圾回收,因此,在池中的每个线程都具有该引用的情况下,它们将使执行程序保持活动状态,直到所有线程都死掉为止。如果您不手动执行某些操作来停止线程,则它们将永远运行,并且您的JVM将永远不会关闭。



 类似资料:
  • 问题内容: 是什么决定了垃圾收集器何时真正收集?它是在一定时间之后还是在一定数量的内存用完之后发生的吗?还是还有其他因素? 问题答案: 它在确定是时候运行时运行。在世代垃圾收集器中,一种常见的策略是在第0代内存分配失败时运行收集器。也就是说,每次你分配一小块内存(大块通常直接放置在“旧”代中)时,系统都会检查gen-0堆中是否有足够的可用空间,如果没有,则运行GC释放空间以使分配成功。然后将旧数据

  • 问题内容: 该问题已发布在某个网站上。我在这里找不到正确的答案,因此我将其再次发布在这里。 我的查询与停止线程无关。让我改一下我的问题。A行(请参见上面的代码)启动一个新线程;和B行使线程引用为空。因此,JVM现在具有一个线程对象(处于运行状态),该对象不存在引用(如B行中的t = null)。所以我的问题是,为什么这个线程(在主线程中不再有引用)一直保持运行状态,直到主线程运行。根据我的理解,线

  • 问题内容: 我在代码的第34行上不断收到LineUnavailableException:https://www.refheap.com/21223 错误显示为。 我正在创建Sound类的多个实例(在我的refheap粘贴中实现)。似乎最初的实例没有问题。但是,当我开始使用相同的音频文件制作Sound对象的新实例时,便开始出现此错误。 知道如何解决吗? EIDT:我认为这个问题的 想法可能是我需要

  • 本文向大家介绍为什么要用线程池? 相关面试题,主要包含被问及为什么要用线程池? 时的应答技巧和注意事项,需要的朋友参考一下 池化技术相比大家已经屡见不鲜了,线程池、数据库连接池、Http 连接池等等都是对这个思想的应用。池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率。** 线程池提供了一种限制和管理资源(包括执行一个任务)。 每个线程池还维护一些基本统计信息,例如已完成任务的数

  • 问题内容: 我想触发许多一次性异步CompletableFutures,例如: 理想情况下,可以在完成后将这些CompletableFutures进行垃圾回收。但是,由于我没有存储参考文献,因此是否有事先收集它们的风险? 问题答案: 您不是在显式地存储引用,而是在内部。该方法创建一个,然后向其提交引用的任务(如果您使用的是公共池)。在返回的变成了依赖于第一,因此也被引用。 一旦完成的执行,将第一个

  • 问题内容: Python使用引用计数方法来处理对象生存期。因此,不再使用的对象将立即被销毁。 但是,在Java中,GC(垃圾收集器)会销毁在特定时间不再使用的对象。 Java为什么选择这种策略,这样做有什么好处? 这比Python方法更好吗? 问题答案: 使用引用计数存在弊端。最常提及的一种是循环引用:假设A引用B,B引用C和C引用B。如果A将其对B的引用删除,则B和C的引用计数仍为1,并且不会被