web-dev-qa-db-ja.com

ExecutorServiceでスケジュールされたデーモンスレッド。これが悪い形式である理由を説明する

ExectuorServiceでスケジュールされたスレッドを正常にシャットダウンするというアイデアには満足しています。つまり、shutdownまたはshutdownNowを呼び出すと、プールで作成されたスレッドが正常に終了します。彼らがinterruptに応答した場合、最終的にetcが呼び出され、クリーンで予測可能な出口(リソースなどをクリーンアップできる場所)が得られることを確認できます。

ただし、以下のように(エグゼキュータのThreadFactoryを介して)スレッドをデーモンに設定した場合。

ExecutorService pool = Executors.newSingleThreadExecutor(new ThreadFactory() {
   @Override
   public Thread newThread(Runnable runnable) {
      Thread thread = Executors.defaultThreadFactory().newThread(runnable);
      thread.setDaemon(true);
      return thread;
   }
});

メインスレッドが終了した後、VMはデーモンスレッドを突然終了します。上記の例では、スケジュールされてから突然終了した(デーモン)スレッドは、finallyブロックと割り込み可能なメソッドはInterruptedExceptionをスローしません。

したがって、ThreadPoolExecutorのプールで使用されているスレッドをデーモンとしてマークすることは悪い習慣だと思う傾向があります...私の質問は本当に私が発声するのを助けることですwhy

ExecutorServiceのスレッドプールでデーモンスレッドを使用するのはなぜ悪い習慣です(または同意しない場合はそうではありません)?特にVM正常なシャットダウン(中断ポリシーがあり、正常に再生されるスレッド)とデーモンスレッドを使用したシャットダウン。

最後のポイントを拡張すると、finalizeThreadPoolExecutorはそれ自体でshutdownを呼び出しますが、デーモンスレッドを使用している場合、finalizeが呼び出された場合はすでに終了している可能性がありますVMによって。では、スレッドプールの動作はどうなりますか?基盤となるスレッドが突然終了した場合、だまされて生きたままになる(VMを終了しない)ことができますか?

私が尋ねている理由の一部は、実際のExectorServiceをシャットダウンする必要性を回避するために使用されているのを見たからです。 itsシャットダウンライフサイクルをバイパスすると悪影響が生じる可能性があるシナリオを考えられますか?これまでのところ、デーモンを使用するために私が思いつくことができる唯一の理由は、ショートカットを取ることであり、それが引き起こす可能性のある予期しない副作用に感謝したいと思います。

20
Toby

executorServiceのスレッドプールでデーモンスレッドを使用するのは悪い習慣ですか?

その特定のExecutorServiceに送信されたタスクが突然終了しても問題がない場合は、それがデーモンスレッドの役割です。ただし、一般に、シャットダウンセレモニーなしで終了しても問題ないタスクは多くないため、デーモンスレッドを選択する場合は、何をしているかを知っておく必要があります。

finalize()は、オブジェクトがガベージコレクションされようとしているのときに呼び出されます。特定のオブジェクトがいつGCdになるかについての保証はなく、ThreadPoolExecutorも例外ではないため、そのfinalize()が呼び出される場合と呼び出されない場合があります。動作は特定のJRE実装によって異なり、同じ実装であっても、時々異なる場合があります。

14
Joonas Pulakka

デーモンスレッドは便利な場合があり、突然終了しなければ、IMOはそれほど役に立ちません。

おそらく、突然終了するのではなく、通常のスレッドが実行されなくなったときに中断される別のタイプのスレッドを想像することができます。これは少し便利かもしれませんが、クリーンアップを行う必要がある場合は、整然としたクリーンアップを実行したいと考えている可能性があります。これにより、この機能の利便性が制限されます。

一方、シャットダウン時にクリーンアップする必要のないタスクがある場合は、デーモンスレッドが非常に便利です。また、デーモンスレッドを使用している理由は、いかなる種類のクリーンアップも必要ないため、特定の状態に到達するのを待つ時間を無駄にしたり、シャットダウンなどでハングアップするリスクを冒したりしたくないでしょう。アプリの場合、何かを実行するのは時間の無駄です。シャットダウンしています。気にするなら、デーモンスレッドを使うべきではありませんでした。

デーモンスレッドプールでも違いはありません。そのスレッドプールがシャットダウン時にクリーンアップを必要としないタスクを実行している場合は、利便性のために意味があります。

JCiPブック から:

デーモンスレッドは慎重に使用する必要があります。クリーンアップなしでいつでも安全に放棄できる処理アクティビティはほとんどありません。特に、あらゆる種類のI/Oを実行する可能性のあるタスクにデーモンスレッドを使用することは危険です。デーモンスレッドは、メモリ内キャッシュから期限切れのエントリを定期的に削除するバックグラウンドスレッドなど、「ハウスキーピング」タスクに最適に保存されます。

5
Enno Shioji

デーモンスレッドと非デーモンスレッドでプールが異なる傾向があります。デーモンプールは、1つまたは2つが実行されないかどうかに関係なく、クリーンアップジョブ、監視、およびバックグラウンドタスクを繰り返し実行する傾向があります。アプリケーションの実行中にのみ意味のあるタスクは、デーモンスレッドタスクを作成するのに適しています。例えばGCスレッドはデーモンスレッドです。

5
Peter Lawrey