2 つの異なる問題があるようです。
1) 作業キューを過剰に供給しています。タスク エグゼキューターの消費率に関係なく、新しいタスクをキューに詰め込み続けることはできません。作業キューへの新しい追加をいつブロックするかを知るためのロジックを理解する必要があります。
2) タスクのスレッドでキャッチされない例外があると、スレッドが完全に強制終了される可能性があります。その場合、ExecutorService は新しいスレッドをスピンアップして、それを置き換えます。しかし、だからと言って、そもそもスレッドが停止する原因となっている問題を無視できるわけではありません。キャッチされていない例外を見つけてキャッチしてください。
これはただの予感です (あなたの投稿には他の方法を知るのに十分な情報がないため) が、あなたの問題はタスク エグゼキュータがタスクの処理を停止することではないと思います。私の推測では、タスクを作成するほど速くタスクを処理しないということです。(そして、タスクが時期尚早に終了することがあるという事実は、おそらく問題と直交しています。)
少なくとも、これはスレッド プールとタスク エグゼキュータを扱った私の経験です。
さて、あなたのコメントに基づいて実現可能な別の可能性があります(突然クラッシュして停止するまで、すべてが何時間もスムーズに実行されます)...
まれに、タスク スレッド間でデッドロックが発生する場合があります。ほとんどの場合、あなたは幸運に恵まれ、デッドロックは現れません。ただし、場合によっては、2 つ以上のタスク スレッドが、他のスレッドによって保持されているロックの解放を待機している状態になることがあります。その時点で、それ以上のタスク処理は実行できなくなり、OutOfMemoryError が発生するまでワーク キューが積み重なっていきます。
その問題を診断する方法は次のとおりです。
タスク スレッド間のすべての共有状態を排除します。最初は、必要なすべての共有データ構造の防御コピーを作成する各タスク スレッドが必要になる場合があります。これが完了したら、デッドロックを経験することは完全に不可能になるはずです。
この時点で、(適切な同期を使用して) 共有データ構造を 1 つずつ徐々に再導入しました。小さな変更を加えるたびにアプリケーションを再実行して、デッドロックをテストします。クラッシュする状況が再び発生した場合は、共有リソースのアクセス パターンを詳しく調べて、本当に共有する必要があるかどうかを判断してください。
私は、スレッド プールとエグゼキューターを使用して並列タスクを処理するコードを作成するときは常に、それらのタスク間ですべての共有状態を排除しようとします。アプリケーションに関する限り、それらは完全に自律的なアプリケーションである可能性があります。デッドロックを突き止めるのは面倒です。私の経験では、デッドロックを解消する最善の方法は、他のタスク スレッドと状態を共有するのではなく、各スレッドが独自のローカル状態を持つことです。
幸運を!