6

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 ループが非常に長時間実行されると想定すると、アプリケーションはメモリ不足になり、クラッシュします。

私の質問: これは本当ですか? もしそうなら、それを避けるために何をすべきですか?

4

5 に答える 5

7

まず、Java GC は非決定論的です。オブジェクトが参照されなくなった場合、次の GC 実行で収集するのに適していますが、必須ではありません。呼び出しでさえSystem.gc()、GC システムへの提案にすぎません。

第二に、重要なのは参照です。ループの各インスタンスで、スレッド オブジェクトへの参照を上書きします。スレッドが終了した場合は、スレッドを収集するためにメソッドを終了する必要はありません (もちろん、コードがスレッドへの参照を持っていなくても、スレッドの実行中はスレッドは収集されません)。オブジェクトが作成されたメソッドを終了する問題は関係ありません。

于 2012-07-13T12:40:31.687 に答える
4

GC は必要なときに実行されます (たとえば、メモリを割り当てようとしたときに Eden スペースがいっぱいになった場合)。

これは、(任意のスレッドで) メモリを割り当てる任意のコード行で発生する可能性があります。つまり、1 つのスレッドでメモリを割り当てなくても、メモリが別のスレッドで割り当てられたために GC が発生する可能性があります。

GC を明示的にトリガーするか、visualvm などの JMX ツールを使用してトリガーすることもできます。

つまり、GC はいつでも発生する可能性があります。

于 2012-07-13T12:40:24.650 に答える
1

MyThreadのすべてのインスタンスは、別のループ反復の開始直後にGCによって収集されるようにマークされます。MyThreadをスレッドとして実行する場合は、start()メソッドを使用する必要があります。

start()メソッドを使用している場合、MyThreadは、別のループ反復の開始直後にGCによって収集されるようにマークされます。run()メソッドの終わり。

ただし、GCによっていつ収集されるかについての保証はありません。これはGC固有のものです。

于 2012-07-13T12:53:39.283 に答える
0

上に投稿したコードでは、実際に並行して実行されているスレッドはありません。新しいスレッドを生成するには、スレッドの.start()メソッドを内部的に呼び出すメソッドを呼び出す必要があります.run()。現在、すべてが順次実行されています。したがって、thread.run() は実行を終了し、現在のスレッドはスリープ状態になり、whileループを継続して何度も実行します。

GC はいつでもヒットする可能性があり、他の人が述べているように、実行中のスレッド (で開始されたスレッドstart()) は、実行が終了した場合にのみ GC されます。

于 2012-12-12T17:07:36.163 に答える
0

ジョブが終了し、それ以上データを使用しない場合よりも後にスレッドで呼び出されることは認められていますが、ガベージ コレクターは仮想マシンによって定期的に、またはいくつかのイベントが発生したときに自動的に呼び出されるため、いつではありません。

そのため、スレッドが終了してデータが使用されなくなったときから、データが自動収集されたかどうかを知ることはできません。

次のように明示的に呼び出すこともできますSystem.gc()

スレッドが終了し、彼が指摘したデータが使用されなくなった場合、明示的な呼び出しの後、収集されたことが認められます。

于 2012-07-13T12:46:20.553 に答える