2

クラスインスタンスがガベージコレクターによって収集されるたびにfinalize()が呼び出されることを私は知っています。ただし、クラスのインスタンスをキューを介して別のスレッドに渡すときは、少し混乱します。

これがThread1のスケルトンであるとしましょう。

for(i=0; i<1000; i++) {
   Packet pkt = new Packet();  // instance of class
   pkt.id = i;
   thread2.queue.put(pkt);
}

次に、スレッド2はパケットをキューから削除し、長時間の操作を実行します。この2番目のスレッドはパケットの「コピー」を取得しますか、それとも何らかの参照によるものですか?重要なのは、コピーによる場合、スレッド1で作成されたインスタンスのfinalize()は、スレッド2がパケットを処理する前に呼び出すことができるということです。参照による場合、finalize()はパケット内の情報に対して1回だけ呼び出されることが保証されています。

この基本的な例は重要性を示していないかもしれませんが、オブジェクトを使い終わったときにメモリを破壊するために、(JNIからの)Cポインターをパケットに格納しています。コピーで渡された場合、2番目のスレッドが完了する前にメモリが破壊される可能性があります。参照によって渡された場合は、GCが両方のスレッドで使用されなくなったことを確認した後でのみ破棄する必要があります(私の望ましい動作)。この後者のシナリオが保証されていない場合は、finalize()を使用せず、他の何かを使用しますが、より複雑になります。

4

1 に答える 1

6

2番目のスレッドは、同じ実際のオブジェクトインスタンスを受け取ります。時期尚早のファイナライズから安全です。

そのように考えたい場合は、オブジェクト参照のコピーを受け取ります。

さらにfinalize、ガベージコレクターがオブジェクトがガベージになったことを検出したときに必ずしも実行されるとは限りません。VMは後でいつでも自由に実行でき、その後しばらくして実際にメモリを再利用できます。いつfinalize実行されるかを本当に信頼することはできません。ただし、気になるのは、2番目のスレッドがオブジェクトで終了する前に呼び出されfinalize ないことを知っていることなので、それは重要ではありません。しかし、知っておく価値があります!

于 2011-07-21T15:58:07.560 に答える