Java线程垃圾收集
当线程中的Java线程垃圾收集,java,multithreading,garbage-collection,Java,Multithreading,Garbage Collection,当线程中的run()方法完成时或从中调用它的函数完成时,是否会收集线程垃圾 我没有任何问题,但我想避免内存泄漏之类的问题 对于喜欢代码的人: public void SomeClass { public SomeClass() { } public void someMethod() { Object data = veryBigObject; while(true) { MyThread thread = n
run()
方法完成时或从中调用它的函数完成时,是否会收集线程垃圾
我没有任何问题,但我想避免内存泄漏之类的问题
对于喜欢代码的人:
public void SomeClass {
public SomeClass() {
}
public void someMethod() {
Object data = veryBigObject;
while(true) {
MyThread thread = new MyThread(veryBigObject);
thread.run();
try {
Thread.sleep(1000);
} catch (InterruptedException e) { /* do nothing */ }
}
}
public static void main(String[] args) {
SomeClass myclass = SomeClass();
myclass.someMethod();
}
}
public class MyThread extends Thread {
private Object data;
public Thread(Object data) {
this.data = data;
}
public void run() {
// do stuff with data
}
}
在我所知道的所有语言中,垃圾(如果该语言有)都是在方法结束时收集的。我想Java也可以。这意味着理论上我在someMethod()
中创建的线程在someMethod()
结束之前不会被收集。如果我们假设while循环运行很长时间,那么应用程序将耗尽内存并崩溃
我的问题:这是真的吗?如果是,如何避免它?GC在需要时运行(例如,当您尝试分配内存且eden空间已满时) 这可能发生在分配内存(在任何线程中)的任何代码行上。这意味着即使您没有在一个线程中分配内存,由于内存分配在另一个线程中,GC仍然可能发生 您还可以显式地触发GC或使用JMX工具(如visualvm)
简而言之:GC可以在任何时候发生。首先,在Java中,GC是不确定的。当对象不再被引用时,它适合在下一次GC运行中收集,但它不是强制的。甚至调用
System.gc()
也只是对gc系统的建议
其次,重要的是引用。在循环的每个实例中,覆盖对线程对象的引用。如果线程已经完成,则无需退出方法来收集它们(当然,当线程正在运行时,即使代码没有引用它们,也不会收集它们)。退出创建对象的方法的问题不相关。允许在线程完成作业后调用该对象,并且不会使用更多数据,但不会在何时调用,因为虚拟机会定期或在某些事件发生时自动调用垃圾收集器 因此,从线程终止和数据未使用时起,您就无法知道dat是否已自动收集 您还可以使用:
System.gc()
明确地调用它
如果您的线程被终止,并且其指向的数据没有被更多地使用,那么在显式调用之后,它被授予已收集的权限。MyThread的每个实例都将在另一个循环迭代开始后被标记为由GC收集。如果要将MyThread作为线程运行,则需要使用start()方法 在使用start()方法的情况下,MyThread将被标记为在另一个循环迭代开始后由GC收集,并且!run()方法的结尾
但是,对于GC何时会收集这些数据没有任何保证。这是一个GC特有的东西。在您上面发布的代码中,实际上没有线程并行执行。要生成新线程,您需要调用
.start()
方法,该方法在内部调用线程的.run()
方法。现在,一切都在按顺序运行。因此,您的thread.run()将完成它的执行,您当前的线程将休眠,而您的while
将继续它的循环并一遍又一遍地执行
GC可以在任何点命中,正如其他人所说,运行线程(使用
start()
启动的线程)只有在完成执行后才会被GCed 在我所知道的所有语言中,垃圾(如果该语言有)都是在方法结束时收集的。点一种语言!你错误地认为垃圾收集W/AutoRealOutlook计数和C++类似的堆栈分配对象析构函数。Java在堆栈上不分配任何对象(根据设计,但通过EA[escape analysis]或ED[escape detection]在技术上是可能的),因此该语句充其量是不正确的(最坏情况下是非常错误的)。真正的并发GC可以在任何时间运行,甚至可以一直运行(尽管后者需要读屏障),因此因为我正在覆盖引用,线程是不可访问的,因此当它完成运行时会被垃圾收集,是吗?“当它完成运行时”除了线程完成运行外,不会发生任何特殊情况。GC可以随时运行。