スレッド プールの作成に ThreadPoolExecutor を使用する必要があるのはなぜですか?

Java 言語では、同時プログラミングはスレッド プールに依存しており、スレッド プールを作成する方法は数多くありますが、広い観点から見ると、スレッド プールの作成は 2 つのカテゴリに分類されます: ThreadPoolExecutor を使用して手動でスレッドを作成する場合 プールとエグゼキュータを使用する場合スレッド プールを自動的に作成します。では、スレッド プールを作成するにはどの方法を使用すればよいでしょうか?

結論から先に話しましょう

Java 言語では、スレッド プールを手動で作成するには ThreadPoolExecutor を使用する必要があります。このメソッドはパラメータを通じてタスクの最大数と拒否戦略を制御でき、スレッド プールの実行をより透過的かつ制御可能にし、リソース枯渇のリスクを回避できるためです。 。

OOM リスクのプレゼンテーション

Executor を使用してスレッド プールを自動的に作成してスレッド プールを作成すると、スレッド オーバーフローのリスクが生じます。CachedThreadPool を例として説明します。
ここに画像の説明を挿入

ステップ 2 次の図に示すように、Idea の JVM の最大実行メモリを 10M に設定します(この値は主にデモンストレーションの便宜のために設定されています)。
ここに画像の説明を挿入

上記プログラムの実行結果を次の図に示します。

上記の結果から、スレッドが 7 回実行されると、OutOfMemoryError メモリ オーバーフローの例外が発生し始めることがわかります。

メモリオーバーフローの原因解析

メモリ オーバーフローの原因を理解するには、CachedThreadPool の実装の詳細を確認する必要があります。そのソース コードを次の図に示します。コンストラクターの 2 番目のパラメーターは、スレッドの最大数を意味する Integer.MAX_VALUE に設定されています
ここに画像の説明を挿入
。 CachedThreadPool はスレッド数を制限しないため、特にタスク数が多い場合には大量のスレッドが作成されます。上記の OOM の例では、各スレッドは少なくとも 1M のメモリを消費し、JDK システム クラスのロードにもメモリの一部が使用されるため、実行メモリの合計が 10M を超えると、メモリ オーバーフローの問題が発生します。

ThreadPoolExecutor を使用して改善する

次に、ThreadPoolExecutor を使用して OOM 問題を改善します。ThreadPoolExecutor を使用してスレッド プールを手動で作成し、最大スレッド数 2 のスレッド プールを作成し、最大 2 つのタスクを保存し、スレッド プールの拒否ポリシーを設定します。新しいタスクを無視して、スレッド プールの実行メモリ サイズが 10M を超えないようにするための実装コードは次のとおりです。
ここに画像の説明を挿入

上記プログラムの実行結果を次の図に示します。
ここに画像の説明を挿入

上記の結果から、実行の開始から終了までスレッド プールに OOM 例外が発生しないことがわかります。これは、スレッド プールを手動で作成することの利点です。

スレッド プールの作成に関するその他の問題

CachedThreadPool スレッド プールに加えて、Executor を使用してスレッド プールを自動的に作成する他の方法にも別の問題があります。たとえば、FixedThreadPool の実装ソース コードは次のとおりです。
ここに画像の説明を挿入

デフォルトでは、タスク キュー LinkedBlockingQueue のストレージ容量は Integer.MAX_VALUE であり、次の図に示すように無限になる傾向があります。
ここに画像の説明を挿入

これにより、スレッド プール内のタスクが多すぎることによって引き起こされるメモリ オーバーフローの問題も発生します。この問題は、Executor を使用してスレッド プールを自動的に作成する他のいくつかの方法にも存在するため、ここでは 1 つずつ説明しません。

要約する

スレッド プールの作成方法は、ThreadPoolExecutor を手動で使用してスレッド プールを作成する方法と、Executor を自動で使用してスレッド プールを作成する方法の 2 つのカテゴリに分類されます。このうち、Executorを使用してスレッドを自動作成する場合、スレッドやタスクの数を制御できないため、メモリオーバーフローの危険性があるため、スレッドプールを作成する場合はThreadPoolExecutorを使用して作成することを推奨します。

おすすめ

転載: blog.csdn.net/qq_36256590/article/details/132382627