モジュール java.base
パッケージ java.util.concurrent

クラスConcurrentHashMap<K,V>

java.lang.Object
java.util.AbstractMap<K,V>
java.util.concurrent.ConcurrentHashMap<K,V>
型パラメータ:
K - このマップで保持されるキーの型
V - マップされる値の型
すべての実装されたインタフェース:
Serializable, ConcurrentMap<K,V>, Map<K,V>

public class ConcurrentHashMap<K,V> extends AbstractMap<K,V> implements ConcurrentMap<K,V>, Serializable
取得の完全な同時性および予想される高い更新平行性をサポートするハッシュ表です。 このクラスは、Hashtableと同じ機能仕様に従い、Hashtableの各メソッドに対応するバージョンのメソッドを含みます。 ただし、すべての操作がスレッド・セーフである場合でも、取得操作にロックは含まれないため、テーブル全体がロックされてすべてのアクセスが拒否されることはありません このクラスは、そのスレッドの安全性に依存するが、その同期の詳細には依存しないプログラムでHashtableと完全に相互運用できます。

通常、取得操作(getを含む)ではブロックは実行されないため、更新操作とオーバーラップする場合があります(putおよびremoveを含む)。 取得では、開始時に保持している更新操作のうち、最後に完了した更新操作の結果が反映されます。 (つまり、指定されたキーの更新操作によって、更新された値を報告するそのキーの(null以外の)取得との間にhappens-before関係が生まれます。) putAllclearなどの集計操作では、並行取得は一部のエントリの挿入または削除だけを反映する可能性があります。 同様に、Iterator、SpliteratorおよびEnumerationは、ある時点またはイテレータおよび列挙の作成以降のハッシュ・テーブルの状態を反映する要素を返します。 これらがConcurrentModificationExceptionをスローすることはありません しかし、一度に1つのスレッドのみがイテレータを使用するように設計されています。 sizeisEmptyおよびcontainsValueを含む集約ステータス・メソッドの結果は、通常、他のスレッドでマップの並行更新が行われていない場合にのみ有効であることに留意してください。 それ以外の場合、これらのメソッドの結果は一時的な状態を反映しているため、モニタリングや推定を目的とする場合には問題ありませんが、プログラムの制御には適していません。

このテーブルは、競合(つまり、別個のハッシュ・コードを持っているが、テーブル・サイズを法とする同じスロットに入るキー)の数が多すぎる場合に動的に拡張され、予想される平均効果として(サイズ変更の負荷係数のしきい値0.75に対応して)マッピング当たりおよそ2個のビンを保持します。 マッピングが追加および削除されると、この平均との差違が大きくなることがありますが、全体としては、ハッシュ・テーブルに関して一般に受け入れられている時間と容量のトレードオフが維持されます。 ただし、このハッシュ・テーブルまたはその他の種類のハッシュ・テーブルのサイズ変更は、相対的に低速な操作である可能性があります。 可能な場合は、サイズの推定値をコンストラクタのオプション引数である initialCapacityとして指定することをお薦めします。 コンストラクタの追加のオプション引数であるloadFactorは、指定された要素数に対して割り当てる領域の量を計算するために使用されるテーブル密度を指定することにより、テーブルの初期容量をカスタマイズする追加手段を提供します。 また、このクラスの前のバージョンとの互換性を保つため、予想されるconcurrencyLevelを初期サイズ設定の追加のヒントとしてコンストラクタにオプションで指定することもできます。 まったく同じhashCode()を持つキーを数多く使用すると、ハッシュ・テーブルのパフォーマンスは確実に低下します。 影響を軽減するため、キーがComparableである場合は、このクラスでキー間の比較順序を使用してキーの重複を解消できます。

キーのみが対象であり、マップされる値が(おそらく一時的に)使用されないか、またはすべてが同じマッピング値を取る場合は、ConcurrentHashMapのSet展開を(newKeySet()またはnewKeySet(int)を使用して)作成または(keySet(Object)を使用して)表示できます。

ConcurrentHashMapは、LongAdder値を使用し、computeIfAbsentを使用して初期化することにより、スケーラブルな周波数マップ(ヒストグラムまたはマルチ・セットの形式)として使用できます。 たとえば、ConcurrentHashMap<String,LongAdder> freqsにカウントを追加するには、freqs.computeIfAbsent(key, k -> new LongAdder()).increment();を使用できます

このクラスとそのビューおよびイテレータは、MapおよびIteratorインタフェースのオプション・メソッドすべてを実装します。

Hashtableと同様に(HashMapとは異なる)、このクラスは、キーまたは値としてnullが使用されることを許可しません

ConcurrentHashMapは、ほとんどのStreamメソッドとは異なり、たとえば共有レジストリ内の値のスナップショット・サマリーを計算するときに、他のスレッドで並行して更新されるマップでも安全(かつ多くの場合適切に)適用されるように設計された一連の順次および並列の一括オペレーションをサポートします。 3種類の操作があり、それぞれに4つのフォームがあり、キー、値、エントリおよび(キー、値)のペアを引数または戻り値(あるいはその両方)として持つ関数を受け入れます。 ConcurrentHashMapの要素は特定の方法で順序付けられておらず、異なる並列実行で異なる順序で処理される可能性があるため、指定された関数の正確性が任意の順序や、計算の進行中に一時的に変更される可能性があるその他のオブジェクトまたは値に依存しないようにしてください。また、forEachアクションの場合を除き、副作用がないことが理想です。 Map.Entryオブジェクトに対する一括オペレーションでは、setValueメソッドはサポートされません。

  • forEach: 各要素に対して指定されたアクションを実行します。 バリアント形式は、アクションを実行する前に各要素に特定の変換を適用します。
  • search: 指定された関数を各要素に適用した最初のnull以外の結果を返します。結果が見つかった場合は、それ以上の検索をスキップします。
  • reduce: 各エレメントを累計します。 指定されたリダクション関数は順序に依存できません(つまり、結合性と交換可能性を持つ必要があります)。 5つのバリアントがあります。
    • 単純なリダクション。 (対応する戻り値の型がないため、(キー、値)関数引数に対応するこのメソッドの形式はありません。)
    • 各要素に適用された特定の関数の結果を累積するマップされたリダクションです。
    • 特定の基準値を使用したスカラーdouble、long、intへのリダクションです。

これらの一括オペレーションは、parallelismThreshold引数を受け入れます。 現在のマップ・サイズが指定されたしきい値より小さいと推定された場合は、メソッドが逐次的に進行します。 Long.MAX_VALUEを使用すると、すべての並列処理が抑制されます。 1を使用すると、すべての並列計算に使用されるForkJoinPool.commonPool()をフル活用するのに十分な数のサブタスクにパーティション化することによって、最大限の並列処理が行われます。 通常は、最初にこれらの極値のいずれかを選択し、その後オーバーヘッドとスループットのバランスを取った中間値を使用してパフォーマンスを計測します。

一括オペレーションの並行性プロパティは、ConcurrentHashMapの並行性プロパティから得られます。get(key)および関連するアクセス・メソッドからnull以外の結果が返されると、関連する挿入または更新との間にhappens-before関係が生まれます。 一括オペレーションの結果は、これらの要素単位の関係の構成を反映します(ただし、なんらかの方法で休止していることがわかった場合を除き、マップ全体に関して原子的である必要はありません)。 逆に、マップ内のキーと値がnullになることはないため、nullは結果が現在存在しないことを確実かつ原子的に示す役割を果たします。 このプロパティを保持するため、nullはすべての非スカラー・リダクション・オペレーションの暗黙的な基準として機能します。 double、longおよびintのバージョンでは、この基準は他の値と結合されたときにその値を返すもの(つまり、リダクションの識別要素)である必要があります。 0を基準とする合計の計算やMAX_VALUEを基準とする最小数の計算など、ほとんどの一般的なリダクションにはこれらのプロパティがあります。

引数として指定される検索および変換関数も、同様に結果が存在しないことを示すためにnullを返す必要があります(その場合、結果は使用されません)。 マップされたリダクションの場合は、これによってフィルタとして機能する変換も可能になります。要素が結合されない場合は、null(プリミティブ特化の場合は識別基準)が返されます。 変換とフィルタリングの複合処理を作成するには、それらを検索またはリデュースのオペレーションで使用する前に、この「nullは現在何も存在しないことを意味する」というルールに従ってそれらを自分で構成します。

Entry引数を受け入れたり、返したりするメソッドは、キーと値の関連付けを保持します。 これらは、たとえば最大値のキーを見つけるときに便利です。 単純なEntry引数は、new AbstractMap.SimpleEntry(k,v)を使用して指定できます。

一括オペレーションは、指定された関数の使用時に検出された例外をスローして、突然完了することがあります。 このような例外を処理するときは、他の並列実行されている関数も例外をスローした可能性があることや、最初の例外が発生しなかった場合は他の並列実行されている関数が例外をスローしたことに留意してください。

逐次形式に比べて並列形式の方が高速化されることは、一般的ですが保証はされません。 計算を並列化するためのベースとなる作業が計算自体より高負荷である場合、小さいマップに対する簡単な関数が関与する並列オペレーションは、逐次形式より実行速度が低くなる可能性があります。 同様に、すべてのプロセッサが無関係のタスクの実行でビジー状態である場合は、並列化しても実際にはそれほど多くの並列処理は行われない可能性があります。

すべてのタスク・メソッドに対するすべての引数は、null以外である必要があります。

このクラスは、Java Collections Frameworkのメンバーです。

導入されたバージョン:
1.5
関連項目: