BAE*_*RUS 20 java multithreading garbage-collection memory-management
简而言之:我有一个完成运行的线程,但没有收集垃圾.
长:请参阅以下示例代码:
public void saveSomething() {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
// heavy memory access (~400 MB), finishes after ~10sec
}
});
thread.start();
}
Run Code Online (Sandbox Code Playgroud)
好的,所以这个线程在一段时间后开始并完成.在此期间使用了大量内存,这没关系.但我的问题是:
线程完成后,内存未设置为空闲
我不知道如何确保这一点.完成的线程,不再使用,应该收到垃圾收集,据我所知; 但这似乎不会发生在这里:(
从jvisualVM看这个截图:

1:我通过调用触发线程启动 saveSomething()
2:线程很久以前就已经完成了(我通过调试看到了它),我在jvisualvm中按下了"Perform GC"
正如你所看到的,在我强制GC之后,一切都按照我想要的方式工作.但这必须自动发生.我怎么能这样做,我做错了什么?
如果您需要更多信息,请询问.注意:似乎在一天(希望更短)后,内存恢复正常,GC可能只是"慢"或者不是经常定时?
Gho*_*ica 34
难道你问的是错误的问题吗?我的意思是:垃圾收集不会"立即"出现问题吗?
我很确定 - 当你启动另一个需要大量内存的线程时,GC将自行启动.
如果"延迟"对您来说实际上是一个问题,您可以考虑进行"非常深入的研究",以了解GC实际上如何适用于您的JVM版本; 然后开始使用现有的许多命令行选项来根据您的需要微调GC行为.
但是,如果释放内存(对其他Java对象)的"延迟"不是问题; 然后不要开始修复它.
Sil*_*ICE 22
线程完成后不会发生垃圾收集.垃圾收集会在发生时发生.当您通过visualvm强制进行垃圾收集时,正确收集线程及其资源意味着一切正常.如果你等待足够长的时间或做更多消耗堆的事情,那么最终你的线程将被GCed.
编辑 唯一需要注意的是,即使没有引用,正在运行的线程也不会被垃圾回收.
Pat*_*han 18
我同意以前的答案.该程序演示了"问题"并非特定于线程创建的事实.通常,gc在需要时或在特别要求时完成.
public class Test {
public static long memInUse(){
Runtime r = Runtime.getRuntime();
return r.totalMemory()-r.freeMemory();
}
public static void main(String[] args){
System.out.println("Initial memory: "+memInUse());
long[] bigArray = new long[1000000];
System.out.println("Memory after array allocation: "+memInUse());
long endTime = System.currentTimeMillis()+10000;
while(System.currentTimeMillis() < endTime){
System.out.println("While array exists: "+memInUse());
try{
Thread.sleep(1000);
}catch(InterruptedException e){
// Deliberately ignore the exception.
}
}
bigArray = null;
System.out.println("After null assignment: "+memInUse());
endTime = System.currentTimeMillis()+10000;
while(System.currentTimeMillis() < endTime){
System.out.println("While array reference null: "+memInUse());
try{
Thread.sleep(1000);
}catch(InterruptedException e){
// Deliberately ignore the exception.
}
}
System.gc();
System.out.println("After gc: "+memInUse());
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
Initial memory: 2684536
Memory after array allocation: 10684552
While array exists: 10684552
While array exists: 10684552
While array exists: 10684552
While array exists: 10684552
While array exists: 10684552
While array exists: 10684552
While array exists: 10684552
While array exists: 10684552
While array exists: 10684552
While array exists: 10684552
After null assignment: 10684552
While array reference null: 10684552
While array reference null: 10684552
While array reference null: 10684552
While array reference null: 10684552
While array reference null: 10684552
While array reference null: 10684552
While array reference null: 10684552
While array reference null: 10684552
While array reference null: 10684552
While array reference null: 10684552
After gc: 1622584
Run Code Online (Sandbox Code Playgroud)
完全有可能JVM在线程完成后根本不需要执行GC,因为它有足够的空闲堆.
只有在需要释放内存时才会执行GC.
就个人而言,我不担心.只要你知道当GC发生时内存将被清除,那就没关系了.
如果你真的想要强制它,你必须在线程完成之后做一个显式的System.GC,或者作为run()方法的最后一行(假设没有对大数据的进一步引用)在那个阶段).
| 归档时间: |
|
| 查看次数: |
4594 次 |
| 最近记录: |