31

使用時の低レベルの違いは何ですか:

ForkJoinPool = new ForkJoinPool(X);

ExecutorService ex = Executors.neWorkStealingPool(X);

ここで、 Xは必要な並列処理のレベル、つまり実行中のスレッドです。

ドキュメントによると、私はそれらが似ていることがわかりました。また、通常の使用ではどちらがより適切で安全か教えてください. BufferedWriterに書き込む 1 億3000万のエントリがあり、Unix ソートを使用して 1 列目でソートします。

また、可能であれば保持するスレッドの数も教えてください。

注:私のシステムには8コアのプロセッサと32 GB の RAM があります。

4

3 に答える 3

52

ワーク スティーリングは、ワーク キューでの競合を減らすために、最新のスレッド プールで使用される手法です。

従来のスレッドプールには 1 つのキューがあり、各スレッド プール スレッドはキューをロックし、タスクをデキューしてから、キューのロックを解除します。タスクが短く、その数が多い場合、キューで多くの競合が発生します。ここでは、ロックフリーキューを使用すると非常に役立ちますが、問題が完全に解決されるわけではありません。

最新のスレッド プールはワーク スティーリングを使用します。各スレッドには独自のキューがあります。スレッドプール スレッドがタスクを生成すると、それは自分のキューにエンキューされます。スレッドプール スレッドがタスクをデキューする場合、最初に自分のキューからタスクをデキューしようとし、タスクがない場合は、他のスレッド キューから作業を「盗み」ます。これにより、スレッドプールの競合が大幅に減少し、パフォーマンスが向上します。

newWorkStealingPoolスレッドの数をプロセッサの数として、workstealing を利用するスレッド プールを作成します。

newWorkStealingPool新たな問題を提示します。4 つの論理コアがある場合、プールには合計 4 つのスレッドがあります。同期 IO などでタスクがブロックされた場合、CPU を十分に活用していません。私が望むのは、任意の時点で 4 つのアクティブなスレッドです。たとえば、AES を暗号化する 4 つのスレッドと、IO が終了するのを待つ別の 140 のスレッドです。

これForkJoinPoolにより、タスクが新しいタスクを生成し、そのタスクが終了するのを待っている場合、プールは CPU を飽和させるために新しいアクティブなスレッドを注入します。ForkJoinPoolこれもワークスティーリングを利用していることに言及する価値があります。

どちらを使用しますか?fork-join モデルを使用している場合、またはタスクが無期限にブロックされることがわかっている場合は、ForkJoinPool. タスクが短く、ほとんどが CPU バウンドの場合は、 を使用しますnewWorkStealingPool

なんと言っても、最新のアプリケーションは、ブロックを防ぐために、利用可能なプロセッサ数でスレッド プールを使用し、非同期 IOロックフリー コンテナを利用する傾向があります。これにより (通常) 最高のパフォーマンスが得られます。

于 2016-12-27T10:36:28.803 に答える
7

newWorkStealingPoolのより高いレベルの抽象化ですForkJoinPool

Oracle jvm の実装を見ると、それは単純に構成済みのForkJoinPool:

public static ExecutorService newWorkStealingPool() {
    return new ForkJoinPool(Runtime.getRuntime().availableProcessors(),
                            ForkJoinPool.defaultForkJoinWorkerThreadFactory,
                            null, 
                            true);
}

残念ながら、実装を見ることは、クラスの目的を理解するための適切な方法ではありません。

クレジット: https://dzone.com/articles/diving-into-java-8s-newworkstealingpools

于 2017-09-05T15:57:19.220 に答える