2016-12-26 13 views
3

概要永続的なバックグラウンドスレッドを維持する方法は?

私は長時間実行する必要がありますサーバーを持って、それはIOのためのいくつかのバックグラウンドスレッドを生成します。バックグラウンド/ IOスレッドがダウンしないようにしようとしているか、スレッドがダウンした場合にそれらが戻ってくるかどうかを確認しようとしています。

現在のソリューション

現在、私のメインループは、単にすべてのバックグラウンドチェック(以下擬似コード)の状態をチェックします。私は良い方法があるはずだと思う。

while (!Thread.currentThread().isInterrupted()) { 
    maintainThreads(); 
    doWork(); 
    condition.await(30, TimeUnit.SECONDS); 
} 

私の試み

私はそれが次のタスクを引いたときRunnableを削除することはできませんカスタムqueueで、SingleThreadExecutorへの切り替えを検討しています。 executorは私のためにスレッドを管理するので、メインループから取り除くことができます。

スレッドごとに1つのエグゼキュータを置くとパフォーマンスが低下し、この問題の解決方法はよりシンプル/優れていると心配です。また、スレッドごとにシャットダウンフックを設定して、スレッドを再起動させることも検討しました。

ご協力いただければ幸いです。

+0

「下に行く」とはどういう意味ですか?コードが含まれているために例外がスローされることを意味しますか? try/catchに 'run()'メソッドの本体をラップするだけで、スレッドが例外で終了するのを防ぐことができます。しかし 'doWork()'の意味をかなり長く考えなければなりません。例外をスローする他のメソッド続けることも可能ですか? – BeeOnRope

+0

[UncaughtExceptionHandler](http://docs.oracle.com/javase/8/docs/api/java/lang/Thread.UncaughtExceptionHandler.html?is-external=true)? – GPI

+0

@BeeOnRope私が維持しているスレッドは、チェックされたすべての例外を既に捕捉しているIO接続( 'doWork()'のプロデューサ)だけです。スレッドが終了する場合は、メインループが回転しているだけです。問題を記録し、接続するまで再作成してください。私の主な質問は、「プログラムが実行されている限りスレッドを実行して、何が問題になったとしても、それを行う最もクリーンな方法は何か」ということです。 – billie

答えて

1

ここでの本当の落とし穴は、あなたがダウンで行くによって何を意味するかである「か、彼らが戻ってアップ彼らはがダウン行かなければもたらされるだろうということ。」

スレッドがJavaで出全体のプロセス自体なしを下ることができ、私はそのことを知っている唯一の2つの方法があります。

  1. run()方法は、終了のいずれかの例外を経由またはrunメソッド仕上げ通常(すなわち、例外的に)。
  2. Thread.stop()があなたのスレッドで呼び出されます。

最初に - Thread.stop()に対処しようとしました(2)最初の - Thread.stop()はうまく動作しないアプリケーションでは大したことではありません。それが呼び出されるとあなたのapplication is already badly brokenが呼び出されるので、それが呼び出されることはほとんどないと見なすことができます。この時点で任意のスレッドを再起動すると、アプリケーションが矛盾した状態になっているため、未定義の効果が生じる可能性があります。

したがって、(1)については、run()が終了しないようにする必要があります。 は通常無限ループを設定しているので、通常は終了しません。例外的に終了させないようにするには、catch (Throwable t)を実行し、エラーを適切に記録した後にループを繰り返してください。

もちろん、後で再登場しないcatch (Throwable t)は、通常、コードの匂いです。それは、あなたが不特定のエラーのいくつかの時間をつかんで、とにかく続けることを決めたということです。エラーは、良質なもの(例えば、リモートクライアントが切断されたためSockedClosedExcpetion)から回復不可能なもの(例えば、OutOfMemoryErrorまたはさらに悪いもの)に及ぶ可能性があります。このスレッドがのいずれかの面で続行したい場合は、タイプの例外を実際に尋ねてください。

アプリケーションが無効な状態であり、続行できない可能性があります。 1つの妥協案は、Exceptionのサブクラスを捕捉し、Error上のアプリケーションを終了することだけです。より慎重なアプローチは、処理する方法がわからない(そして修正するバグとして扱う)あらゆるタイプの例外についてアプリケーションを終了させることです。

1

永続的なバックグラウンドスレッドを維持する重要な部分は、スレッドレベルで例外を正しく処理することです。エラー状態、特にトップレベルのサーバー/デーモンコードの例外を処理する場合、いくつかの例外は処理できないことに注意する必要があります。このような例外が発生した場合は、すぐに終了するか、可能な限りクリーンにしてから終了してください。

たとえば、エラータイプのほとんどの例外を処理するべきではありません。これには、java.lang.VirtualMachineError例外:InternalError、OutOfMemoryError、StackOverflowError、UnknownErrorなどが含まれます。これまでの回答で言及したように、Throwableをキャッチすることは多くの例外を取り除くことができない大きなNo-あなたの失敗戦略を考えてみましょう。失敗すると意味があります。この場合は何ができますか(エラーを記録するか、ユーザーにメッセージを表示することができます)。

スレッドをクリーンアップし、正常にシャットダウンする時間があるので、InterruptedExceptionは常に正しく処理してください。それ以外の場合は、データの破損の危険があります。

例外処理のヒントについては、Exceptions Guidelinesの記事を確認してください。

0

アプリケーションプログラムでは、プロセス(スレッドではない)の再作成/再起動が最も信頼性の高いフェールリカバリ方法です。

実際にミッションクリティカルなシステムがどのように障害を処理していますか?冗長性、ハートビート監視、高速ハンドオーバなどを提供することにより、

既に失敗したスレッドを盲目的なものにしないでください。私たちのプロセスに大きな損害を与える原因には多くのものがあり、私たち(人間)はそれらの原因のほんのいくつかしか知りません。

私たちがFAIL FASTを実行してプロセスを再起動すると、OSカーネルが初期状態をクリーンアップできるようにします。だから私たちのプログラムがあまり信頼性が高くない場合でも、プログラムは実行され、ある程度の時間内に仕事をします。

関連する問題