Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/353.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java线程垃圾收集_Java_Multithreading_Garbage Collection - Fatal编程技术网

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可以随时运行。