Executors.newFixedThreadPool(8)によって作成されたExecutorServiceの8つのスレッドで実行される5000の同様のCallableタスクがあります。各タスクはデータベースに移動して、処理する大量のデータを取得します。
すべてが99%の時間正常に動作しますが、DBが遅いかスタックしている場合(理由は聞かないでください)、ログファイルに非常に奇妙な実行ログメッセージが表示されることがあります。現在実行中の8つのタスクが停止し、8つのスレッドすべてでまだ完了していません。 、ExecutorServiceは、1つずつ実行するタスクの送信を開始します。
したがって、ログは、ある時点でExecutorServiceがクレイジーになり、前のタスクが完了するのを待たずに、待機キュー内のCallableのCallableのcall()メソッドの呼び出しを開始することを示しています。ますます多くのタスクがDBにリクエストを送信し、最終的にDBがひざまずき、Javaヒープメモリが使い果たされます。
ExecutorService内で何か奇妙なことが起こっているか、状況の私の理解が間違っているようです。誰かがそのようなものを見たことがありますか?
私の脳のスタックが溢れています
psは、JavaAPIからの引用です。
Executors.newFixedThreadPool(int nThreads)
共有の無制限キューで動作する固定数のスレッドを再利用するスレッドプールを作成します。どの時点でも、最大でnThreadsスレッドがアクティブな処理タスクになります。すべてのスレッドがアクティブなときに追加のタスクが送信されると、スレッドが使用可能になるまでキューで待機します。シャットダウン前の実行中に障害が発生したためにスレッドが終了した場合、後続のタスクを実行するために必要な場合は、新しいスレッドが代わりに使用されます。
これは実際に私のタスクによってスレッドが停止し、ExecutorServiceがより多くのスレッドを作成して新しい8つのタスクをそれらに送信し、それらが停止してExecutorServiceがさらに8つのスレッドを作成し、さらに8つのタスクを送信するということが起こりますか?
pss:Callableのcall()内の操作全体がtry catchで囲まれているため、操作内で例外が発生した場合、例外がキャプチャされてログに記録されます。これは何も起こっていません。呼び出しが呼び出されて戻ることはありませんが、次のタスクは1つずつ呼び出され、戻ることも終了することも、例外をスローすることもありません。
自分のタスクが原因でスレッドプール内のスレッドが停止しているのではないかと思います。どうすれば模倣できますか?