6

java.util.concurrent.ExecutorServiceを呼び出して取得した を使用していExecutors.newSingleThreadExecutor()ます。これExecutorServiceにより、シャットダウンされておらず、例外をスローすることなく新しいタスクを受け入れ続けている場合でも、タスクの処理が停止することがあります。OutOfMemoryError最終的に、アプリが例外でシャットダウンするのに十分な数のキューが構築されます。

ドキュメントは、このシングル スレッド エグゼキュータは、必要に応じて新しいワーカー スレッドを起動して、停止したスレッドを置き換えることにより、タスク処理エラーを乗り切る必要があることを示しているようです。何か不足していますか?

4

3 に答える 3

10

2 つの異なる問題があるようです。

1) 作業キューを過剰に供給しています。タスク エグゼキューターの消費率に関係なく、新しいタスクをキューに詰め込み続けることはできません。作業キューへの新しい追加をいつブロックするかを知るためのロジックを理解する必要があります。

2) タスクのスレッドでキャッチされない例外があると、スレッドが完全に強制終了される可能性があります。その場合、ExecutorService は新しいスレッドをスピンアップして、それを置き換えます。しかし、だからと言って、そもそもスレッドが停止する原因となっている問題を無視できるわけではありません。キャッチされていない例外を見つけてキャッチしてください。

これはただの予感です (あなたの投稿には他の方法を知るのに十分な情報がないため) が、あなたの問題はタスク エグゼキュータがタスクの処理を停止することではないと思います。私の推測では、タスクを作成するほど速くタスクを処理しないということです。(そして、タスクが時期尚早に終了することがあるという事実は、おそらく問題と直交しています。)

少なくとも、これはスレッド プールとタスク エグゼキュータを扱った私の経験です。


さて、あなたのコメントに基づいて実現可能な別の可能性があります(突然クラッシュして停止するまで、すべてが何時間もスムーズに実行されます)...

まれに、タスク スレッド間でデッドロックが発生する場合があります。ほとんどの場合、あなたは幸運に恵まれ、デッドロックは現れません。ただし、場合によっては、2 つ以上のタスク スレッドが、他のスレッドによって保持されているロックの解放を待機している状態になることがあります。その時点で、それ以上のタスク処理は実行できなくなり、OutOfMemoryError が発生するまでワーク キューが積み重なっていきます。

その問題を診断する方法は次のとおりです。

タスク スレッド間のすべての共有状態を排除します。最初は、必要なすべての共有データ構造の防御コピーを作成する各タスク スレッドが必要になる場合があります。これが完了したら、デッドロックを経験することは完全に不可能になるはずです。

この時点で、(適切な同期を使用して) 共有データ構造を 1 つずつ徐々に再導入しました。小さな変更を加えるたびにアプリケーションを再実行して、デッドロックをテストします。クラッシュする状況が再び発生した場合は、共有リソースのアクセス パターンを詳しく調べて、本当に共有する必要があるかどうかを判断してください。

私は、スレッド プールとエグゼキューターを使用して並列タスクを処理するコードを作成するときは常に、それらのタスク間ですべての共有状態を排除しようとします。アプリケーションに関する限り、それらは完全に自律的なアプリケーションである可能性があります。デッドロックを突き止めるのは面倒です。私の経験では、デッドロックを解消する最善の方法は、他のタスク スレッドと状態を共有するのではなく、各スレッドが独自のローカル状態を持つことです。

幸運を!

于 2008-12-05T19:01:37.327 に答える
3

私の推測では、あなたのタスクは死ぬのではなく、無期限にブロックされていると思います. タスクの最後のログ ステートメントなど、タスクが正常に完了したことを示す証拠はありますか?

これは、デッドロック、またはブロックしている外部プロセスとの相互作用である可能性があります。

于 2008-12-05T19:52:20.517 に答える
1

確かな詳細を残していませんが、最初に試みることは、タスクが最上位で「例外」をキャッチし、メッセージをログに記録することです。

正しくないように見えることはわかっていますが、(多くの変数に応じて) スレッドで発生したことが例外をスローし、ログに記録されない、または単に表示されないコードに取り組んだことがあります。コンソール - しかし、「実行中」のコードは、トップレベルのループや、タスクを実行させているコードから抜け出します。

タスクが例外をスローしていないことを確認してください。

于 2008-12-05T19:02:22.943 に答える