ワーク スティーリングは、ワーク キューでの競合を減らすために、最新のスレッド プールで使用される手法です。
従来のスレッドプールには 1 つのキューがあり、各スレッド プール スレッドはキューをロックし、タスクをデキューしてから、キューのロックを解除します。タスクが短く、その数が多い場合、キューで多くの競合が発生します。ここでは、ロックフリーキューを使用すると非常に役立ちますが、問題が完全に解決されるわけではありません。
最新のスレッド プールはワーク スティーリングを使用します。各スレッドには独自のキューがあります。スレッドプール スレッドがタスクを生成すると、それは自分のキューにエンキューされます。スレッドプール スレッドがタスクをデキューする場合、最初に自分のキューからタスクをデキューしようとし、タスクがない場合は、他のスレッド キューから作業を「盗み」ます。これにより、スレッドプールの競合が大幅に減少し、パフォーマンスが向上します。
newWorkStealingPool
スレッドの数をプロセッサの数として、workstealing を利用するスレッド プールを作成します。
newWorkStealingPool
新たな問題を提示します。4 つの論理コアがある場合、プールには合計 4 つのスレッドがあります。同期 IO などでタスクがブロックされた場合、CPU を十分に活用していません。私が望むのは、任意の時点で 4 つのアクティブなスレッドです。たとえば、AES を暗号化する 4 つのスレッドと、IO が終了するのを待つ別の 140 のスレッドです。
これForkJoinPool
により、タスクが新しいタスクを生成し、そのタスクが終了するのを待っている場合、プールは CPU を飽和させるために新しいアクティブなスレッドを注入します。ForkJoinPool
これもワークスティーリングを利用していることに言及する価値があります。
どちらを使用しますか?fork-join モデルを使用している場合、またはタスクが無期限にブロックされることがわかっている場合は、ForkJoinPool
. タスクが短く、ほとんどが CPU バウンドの場合は、 を使用しますnewWorkStealingPool
。
なんと言っても、最新のアプリケーションは、ブロックを防ぐために、利用可能なプロセッサ数でスレッド プールを使用し、非同期 IOとロックフリー コンテナを利用する傾向があります。これにより (通常) 最高のパフォーマンスが得られます。