垃圾回收器不会立即收集完成的线程

简而言之:我有一个线程,它已完成运行,但未被垃圾回收。

长篇大论:请参阅以下示例代码:

public void saveSomething() {
    Thread thread = new Thread(new Runnable() {

         @Override
         public void run() {
             // heavy memory access (~400 MB), finishes after ~10sec
         }
    });
    thread.start();
}

好的,所以这个线程在一段时间后开始和完成。在此期间,使用大量内存,这没关系。但我的问题是:

线程完成后,内存未设置为可用

我不知道我该如何确保这一点。完成的线程,不再使用,应该收集垃圾,据我所知;但这似乎没有发生在这里:(

请参阅来自 jvisualVM 的屏幕截图:

enter image description here

1:我通过调用来触发线程启动saveSomething()

2:线程很久以前就完成了(我通过调试看到了它),我在jvisualvm中按了“执行GC”

如您所见,在我强制GC之后,一切都按照我想要的方式工作。但这必须自动发生。我该怎么做,我做错了什么?

如果您需要更多信息,请询问。注意:似乎一天后(希望更短)内存恢复正常,也许GC只是“慢”或不是很频繁地计时?


答案 1

可能是你问错了问题吗?我的意思是:垃圾回收没有“立即”发生的事实对你来说是一个问题吗?

我很确定 - 当您启动另一个需要大量内存的此类线程时,GC将自行启动。

如果这种“延迟”对您来说确实是一个问题,您可以考虑进行“非常深入的潜水”,以了解GC实际上如何适用于您的JVM版本;然后开始使用现有的许多命令行选项来微调 GC 行为以满足您的需求。

但是,如果释放内存(到其他Java对象)的“延迟”不是问题;然后不要开始修复它。


答案 2

线程完成后不会立即进行垃圾回收。垃圾回收将在发生时发生。当您通过 visualvm 强制垃圾回收时,线程及其资源被正确收集,这一事实意味着一切正常。如果您等待足够长的时间或执行更多消耗堆的事情,那么最终您的线程将被GCed。

编辑唯一需要注意的是,即使没有引用,正在运行的线程也不会被垃圾回收。