23

重複の可能性:
Javaスレッドガベージが収集されたかどうか

次のクラスについて考えてみます。

class Foo implements Runnable {

  public Foo () {
       Thread th = new Thread (this);
       th.start();
  }

  public run() {
    ... // long task
  }

}

Fooを行うことによってのいくつかのインスタンスを作成する場合

new Foo();
new Foo();
new Foo();
new Foo();

(それらへのポインターを保持しないことに注意してください)。

  1. これらのインスタンスは、スレッドが終了するにガベージコレクターによって削除できますか?run()(言い換えると、Fooオブジェクトへの参照はありますか?)

  2. 一方、これらのインスタンスは、 `run()'のスレッドが終了した後、GCによって削除されますか、それともメモリを浪費していますか(「メモリリーク」)?

  3. 1.または2.のいずれかが問題である場合、それを行う正しい方法は何ですか?

ありがとう

4

5 に答える 5

22
  1. アクティブなスレッドによって参照されるオブジェクトは、割り当て解除できません。
  2. はい、`run()' のスレッドが終了した後、インスタンスは GC によって削除されます。
  3. 問題ありません。
于 2012-04-30T08:08:24.817 に答える
12
  1. これらのインスタンスは、run() のスレッドが終了する前にガベージ コレクターによって削除される可能性がありますか? (つまり、Foo オブジェクトへの参照はありますか?)

いいえ。コンストラクターが実行されている間、GC はオブジェクトを収集しません。それ以外の場合は、最も単純なものでも:

Customer c = new Customer();

のコンストラクターの実行中に失敗する可能性がCustomerあります。一方、新しいスレッドを開始すると、スレッド オブジェクトは新しいGC ルートになるため、そのオブジェクトによって参照されるすべてのものはガベージ コレクションの対象になりません。

  1. 一方、これらのインスタンスは「run()」のスレッドが終了した後に GC によって削除されるのでしょうか、それともメモリを浪費しているのでしょうか (「メモリ リーク」)?

スレッドが完了すると、GC ルートではなくなります。そのスレッド オブジェクトを指すコードが他にない場合は、ガベージ コレクションが実行されます。

  1. 1.または2.のいずれかが問題である場合、正しい方法は何ですか?

あなたのコードは問題ありません。でも:

  • コンストラクターで新しいスレッドを開始することは、単体テストの観点からは悪い考えです

  • 実行中のすべてのスレッドへの参照を保持しておくと、後でこれらのスレッドを中断したい場合などに役立ちます。

于 2012-04-30T08:10:31.947 に答える
8

スレッド グループを指定せずに新しいスレッドを開始すると、デフォルト グループに追加されます

group が null で、セキュリティ マネージャが存在する場合、グループはセキュリティ マネージャの getThreadGroup メソッドによって決定されます。グループが null でセキュリティ マネージャがない場合、またはセキュリティ マネージャの getThreadGroup メソッドが null を返す場合、グループは、新しいスレッドを作成しているスレッドと同じ ThreadGroup に設定されます。

グループは、スレッドが存続している限りスレッドへの参照を保持するため、その間は GC できません。

スレッドが終了すると (=run()なんらかの理由で復帰したとき)、そのスレッドはスレッド グループから削除されます。exit()これは、ネイティブ コードから呼び出されるプライベート メソッドで発生します。これは、スレッドへの最後の参照が失われ、GC の対象となる時点です。

コードはそれThreadGroupが可能であることを示していますnullが、そうではないことに注意してください。さまざまな null チェックは、まれに何か問題が発生した場合に NPE を回避するためのものです。ではThread.init()、Java がスレッド グループを判別できなかった場合、NPE が発生します。

于 2012-04-30T08:14:12.553 に答える
3
  1. Fooオブジェクトはスレッドによって参照されます。スレッドは実行中に常に参照されます。したがって、ガベージ コレクションは行われません。
  2. メモリリークはありません。スレッドは終了し、このプロセスでもガベージ コレクションとFooオブジェクトが実行されます。
  3. それはうまくいくはずです。
于 2012-04-30T08:08:37.277 に答える
0

runメソッドでオブジェクトを作成しているとすると、runメソッドが終了するとオブジェクトはスコープ外になり、ガベージコレクションに使用できるようになります。実行は単なる別の方法です。スレッドを使用するかどうかは、ここでのガベージコレクションの動作を変更するものではありません。注意する必要があるのは、オブジェクトがスコープから外れるときだけです。これは通常、ブロックスコープ(メソッドブロック、whileループ、ifブロックなど)に関連付けられています。

したがって、最初からオブジェクトへの参照を保持していないため、オブジェクトを作成するロジックを独自の短期間のメソッドに抽出することをお勧めします。そうすれば、作成されたオブジェクトをそのメソッドの範囲を超えて保持する必要がなくなります。

于 2012-04-30T08:47:26.933 に答える