8

Java ConcurrentHashMap はパーティションを内部的に維持します。各パーティションは個別にロックできます。複数のスレッドによってアクセスされるすべてのキーが同じパーティションに分類され、パーティションが役に立たないシナリオが存在する可能性があります。パーティションの数をさらに増やすと、同時実行性が向上するはずです。

Java がパーティション数のデフォルト値を非常に高い値ではなく 16 として提供するのはなぜですか? マップ内に多数のパーティションがある場合のパフォーマンス オーバーヒアリングはどのようなものですか?

4

2 に答える 2

6

Java がパーティション数のデフォルト値を非常に高い値ではなく 16 として提供するのはなぜですか?

これほど多くの CPU (スレッドの数はそれほど重要ではありません) が同じ CHM を同時に使用することは非常にまれです。これが本当に必要な場合は、通常、これを回避するアプリケーションを作成するためのより良い方法があります。

たとえば、1000 個のスレッドがあり、CPU が 8 個しかないとします。これは、あなたのプログラムが何の役にも立たないと仮定すると、最大で 8 つのスレッドだけが実行され、CHM にアクセスすることを意味します。

実際のプログラムでは、1 つのコレクションが 10% 以上使用されることはまれです。これは通常、何らかの IO が関与するためです。または、スレッドを再構築してコレクションの独自のコピーを使用し、最後にそれらをまとめて収集することが理にかなっているからです (Map-Reduce など)。

マップ内に多数のパーティションがある場合のパフォーマンス オーバーヒアリングはどのようなものですか?

重要ではないメモリを少し無駄にしますが、ほとんどの場合、32 KB に制限された L1 キャッシュと比較的貴重なリソースを無駄にします。

于 2013-06-21T11:22:05.023 に答える
2

javadocの内容は次のとおりです(Java 6):

「更新操作間で許可される同時実行数は、オプションの concurrencyLevel コンストラクター引数 (デフォルト 16) によってガイドされます。これは、内部サイジングのヒントとして使用されます。テーブルは内部的に分割され、指定された数の同時更新を競合なしで許可しようとします。ハッシュ テーブル内の値は基本的にランダムであり、実際の同時実行性はさまざまです. 理想的には、テーブルを同時に変更するスレッド数に対応できる値を選択する必要があります. 必要以上に大きな値を使用すると、スペースと時間が無駄になる可能性があります.より低い値はスレッドの競合につながる可能性があります. しかし, 1桁以内の過大評価と過小評価は通常, 顕著な影響を与えることはありません. 1つのスレッドのみが変更され, 他のスレッドはすべて読み取りのみであることがわかっている場合は, 1の値が適切です. また,このハッシュ テーブルやその他の種類のハッシュ テーブルのサイズを変更する操作は比較的時間がかかるため、可能な場合は、コンストラクターで予想されるテーブル サイズの見積もりを提供することをお勧めします。」

したがって、短い答えは、デフォルト値 (16) は同時実行数の制限とスペースの浪費の間の妥協点であるということです。「非常に高い」値は、多くのスペースを浪費します。(そして、Peter Lawrey が指摘しているように、メモリ キャッシュの影響により、パフォーマンスが低下する可能性があります。)

注意すべきもう 1 つの点は、LinkedHashMap実装が暗黙のうちにconcurrencyLevelat 2 16の値を制限していることです。(少なくとも、それは Java 6 コードが行うことです。) ただし、これほど多くの並行性が必要になる現実世界のシナリオを想像するのは困難です。

于 2013-06-21T11:30:41.480 に答える