2011-07-21 10 views
2

ガベージコレクタによってクラスインスタンスが収集されるたびにfinalize()が呼び出されることはわかっています。しかし、私は、クラスのインスタンスをキュー経由で別のスレッドに渡すときにちょっと混乱します。このシナリオでは、クラスインスタンスでfinalize()が呼び出されるのはいつですか?

のは、これはスレッド1のスケルトンであるとしましょう:

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回だけ呼び出されることが保証されています。

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

+0

javaメソッドの引数との最も近いC/++の比較は、それらが値渡しのポインタであることです。だからそれはコピーであるが、ポインタのコピーだけである。 (誰の操作でも参照を外すだけです)システムのどこかにオブジェクトの場所を指すポインタが1つある限り、その場所は収集されません。 – Affe

+0

C-ポインタをクリーンアップし、finalizeメソッドに依存しないか、ファイナライズメソッド –

答えて

6

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

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

また、ガベージコレクタがオブジェクトがガベージになったことを検出したときに、finalizeが必ず実行されるわけではありません。後でVMを実行しても、実際にはその後すぐにメモリを再利用できます。あなたは本当にfinalizeが実行されるときに頼ることはできません。しかし、あなたが心配しているのは、finalizeがオブジェクトで終了する前にが呼び出されないということなので、それは重要ではありません。しかし、知る価値がある!

+0

を持っていても、Packetにクリーンアップメソッドを追加することを強くお勧めします。迅速な対応に感謝します。これは私にとって事物を大きく単純化します:) – gnychis

+1

finalize()を実行する前にオブジェクトを収集しません! finalizeをオーバーライドするオブジェクトは、優先度の低いスレッドで処理されるファイナライザキューに格納されます。これがfinalize()を避けるべきもう一つの理由です。 –

+0

@Damokles:まあまあ正しい。私の言い訳は、それを指摘してくれてありがとうございました。私はうまくいけば、より正確に言い換えました。 –

関連する問題