6

この質問はしばらくの間私を悩ませますが、まだ完全な答えは見つかりませんでした (たとえば、これは C# の外部または内部の使い捨てリソースを try/finally で初期化するためのものです)。次の 2 つの Java コード フラグメントを検討してください。

Closeable in = new FileInputStream("data.txt");
try {
    doSomething(in);
} finally {
    in.close();
}

そして第二のバリエーション

Closeable in = null;
try {
    in = new FileInputStream("data.txt");
    doSomething(in);
} finally {
    if (null != in) in.close();
}

私が心配しているのは、リソースが取得された瞬間 (ファイルが開かれたときなど) にスレッドが多少中断される可能性があることですが、結果の値はそれぞれのローカル変数に割り当てられません。上記の点でスレッドが中断される可能性があるシナリオは他にありますか?

  1. InterruptedException (例: Thread#interrupt() 経由) または OutOfMemoryError 例外がスローされる
  2. JVM の終了 (例: kill、System.exit() 経由)
  3. ハードウェア障害 (または完全なリストについては JVM のバグ :)

2番目のアプローチはやや「慣用的」であると読みましたが、上記のシナリオではIMOに違いはなく、他のすべてのシナリオでは同等です。

だから質問:

2つの違いは何ですか?リソースの解放を懸念している場合 (特にマルチスレッド アプリケーションの場合)、どちらを選択する必要がありますか? なんで?

回答をサポートする Java/JVM 仕様の一部を教えていただければ幸いです。

4

3 に答える 3

6

心配する理由はないと思います。

1)InterruptedException(例:Thread#interrupt()経由)

呼び出しは、自発的にスローされることThread.interrupt()はありません。InterruptedException例外は、特定の(そして十分に文書化された)ブロッキングメソッド内でのみスローされます。つまり、I/Oと同期方法をブロックします。この例外は、ストリームコンストラクターから戻った後、tryブロックに入る前にスローすることはできません。

またはOutOfMemoryError例外がスローされます

がスローされた場合OutOfMemoryError、ストリームコンストラクターをどこに置いても、基になるファイル記述子の完全な回復を保証することはできません。OOMからの回復を試みるべきではないので、ストリームが閉じているかどうかの問題は議論の余地があります。さらに、この例外は、実際にメモリを割り当てようとしているスレッドでのみスローされ、現時点では発生していません。

2)JVMが終了します(たとえば、kill、System.exit()を介して)

アプリケーションが外部killまたはSystem.exit()呼び出しによって強制的に終了されている場合、ストリームが適切に閉じられているかどうかは関係ありません。また、どちらの場合も、finally句が実行される保証はありません。

3)ハードウェア障害(または完全なリストについてはJVMのバグ:)

すべての賭けはオフです。最後にブロックすることは言うまでもなく、何かが実行されるかどうかを知る方法はありません。

スレッドがその時点で自発的な例外を受け取る可能性があるもう1つの状況があり、スレッドが回復する可能性があるという(素朴な)期待があります。これは、誤った方向に進んだプログラマーが非推奨のThread.stop()メソッドを呼び出すことを決定したときです。tryストリームコンストラクター呼び出しをブロック内に配置すると役立つと思うかもしれません。ただし、実際にはそうではありません。基になるファイルを開いてからストリームオブジェクトの構築が完了するまでの間に、ストリームコンストラクターThreadDeathで例外が発生する可能性があるためです。したがって、FDはとにかくリークする可能性があります。

Thread.stop()これが、廃止される理由の1つにすぎません。使用しないでください。

于 2010-04-28T07:40:45.617 に答える
5

a)interrupt()でスレッドを中断してもすぐには有効にならず、中断されているスレッドが協力しない場合はまったく効果がない可能性があることに注意してください。:の実行中にinterrupt()が原因でスレッドが終了する方法はありません。

Closeable in = new FileInputStream("data.txt");

発生する唯一のことは、スレッドの割り込みフラグがオンになることです。

b)OutOfMemoryErrorについて-入力ストリームの構築直後にどのように発生するかわかりません。別のスレッドで発生する可能性がありますが、これはこのスレッドにすぐには影響しません。OutOfMemoryErrorの問題は、finallyブロックを完了するのに十分なメモリがないため、finallyブロックも失敗する可能性があることです...

c)スレッドが積極的に中断される可能性があることを私が知っている唯一の方法は、非推奨のメソッドThread.stop()およびThread.stop(Throwable)を使用することです。ここで同様の議論を参照してください: これはJavaでリソースを解放するための安全な方法ですか?

于 2010-04-28T07:18:13.823 に答える
0

私の見解では、Javaや.NETなどのマネージドランタイムを使用している場合、特定の質問のようなことを気にする必要はありません(そしてそれは良いことです!)。基盤となるオペレーティングシステムとそのネイティブAPIから完全に切断されているからです。知っておく必要があるClosable.close()のは、finallyブロックを呼び出すだけで、リソースは常に解放されます。

于 2010-04-28T07:04:33.373 に答える