ConcurrrentMapの分析と思考
3416 ワード
予備知識でhashmapの記憶構造が分かります.
(画像からhttp://www.ibm.com/developerworks/cn/java/j-lo-hash/)
つまり、一つのhashmapの内部にはEnttityクラスの行列が含まれています.この配列の要素は全部Entityです.実際にmapに入れたkeyとvalueは一つのEntityオブジェクトに対応しています.このEntityオブジェクトは一つのkey、value、hashcodeと一つのEntityの参照を含んでいます.この参照によってEntityはチェーンテーブルを形成することができます.図では、青い四角形のブロックは配列を表し、オレンジ色の楕円はEntityオブジェクトを表しています.
注意HashMap類はスレッド安全ではありません.
コンカレントMap 主なサブクラスはコンカレントHashMapです.
原理:一つのConcerenthashMapは複数のsegmentからなり、各segmentは一つのEntityの配列を含みます.ここはHashMapよりsegment類が一つ多いです.このクラスはRentrant Lock類を継承していますので、自身はロックです.マルチスレッドがConcerenthashMapに対して動作するときは、mapを完全にロックするのではなく、対応するsegmentをロックします.これによって合併効率が向上しました.
構造関数の分析:
[java]view play copy print?
//* * Creates a new,empty map with a default initial capacity(16)、 * load factor(0.75)and concurrencyLevel(16). */ public ConcerenthashMap(){ this(DEFAULTU_INITIAL LuCAPACITY、DEFAULT_LOAD FACTOR、DEFAULT_CONCURRENCYUVEL); } //Creates a new、empty map with a default initial capacity(16)、*load factor(0.75)、and concurrencyLevel(16)、*/public ConcerenthashMap(){this(DEUFLTty INITIALuCACITY,DECTULTU)
これはコンカレントHashMapの無参画構造関数であり、デフォルトの大きさは16、負荷因子は0.75、同時レベルは16と見られます.
Put関数の分析:
[java]view play copy print?
//* * Maps the specified key to the specified value in this table. * Neither the key nor the value can be null. * * The value can be retrieved by caling the get method * with a key that is equal to the original key. * * @param key with which the specified value is to be assicated * @param value value to be assicated with the specified key * @return the previous value assciated with key,or * null if there wasのmapping for key * @throws Null PointerException if the specified key or value is null */ public V put(K key,V value){ if(value==null) throw new Null PointerException() int hash=hash(key.hashCode); return segmentFor.put(key,hash,value,false); } Maps the speciiifrid key to the speciiiiiifd value in thistablble*Neither the key nor the value can be null.*The value can be retrieved bycalcarived the get method*with a key aaaaaaaaaththththisisaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasasasasasasasasasato be assicated with the specified key@return the previous value asassited with key、or*null if there wasのmapping forkey*@throws Null Point Exception ithe speciiiiiifed or value isnull*/public V put(K key、V valuint=valuint============vavaluefffftttttttttttttttfffffffffffffffttttttttttttttttttttffffffffffffffffffffffffsegmentFor.put(key,hash,value,false);
hash()関数によってkeyのハッシュ値が得られ、対応するsegmentが得られ、segmentによってEntityが格納されていることが分かる.
また、「再検出」(条件付きスレッド安全参照[2])などの合併問題を避けるために、ConcerenthashMapはputIfAbsent(K key,V value)を提供しています. 方法は、keyが存在しない場合に追加します.(keyの存在は二つの条件、一つはkeyのhashcode方法、もう一つはkeyのequal方法です.)
長所:対応するsegmentのため 全体のmapをロックするのではなく、ロックをかけて、合併性を高めました.挿入、検索、除去操作の伸縮性を直接高めることができます.
短所:mapの要素を遍歴するときは、全てのsegmentのロックを取得して、遍歴を使用すると遅くなります.ロックの増加は、システムのリソースを占有します.このセット全体を動作させるいくつかの方法(例えば、
(画像からhttp://www.ibm.com/developerworks/cn/java/j-lo-hash/)
つまり、一つのhashmapの内部にはEnttityクラスの行列が含まれています.この配列の要素は全部Entityです.実際にmapに入れたkeyとvalueは一つのEntityオブジェクトに対応しています.このEntityオブジェクトは一つのkey、value、hashcodeと一つのEntityの参照を含んでいます.この参照によってEntityはチェーンテーブルを形成することができます.図では、青い四角形のブロックは配列を表し、オレンジ色の楕円はEntityオブジェクトを表しています.
注意HashMap類はスレッド安全ではありません.
コンカレントMap 主なサブクラスはコンカレントHashMapです.
原理:一つのConcerenthashMapは複数のsegmentからなり、各segmentは一つのEntityの配列を含みます.ここはHashMapよりsegment類が一つ多いです.このクラスはRentrant Lock類を継承していますので、自身はロックです.マルチスレッドがConcerenthashMapに対して動作するときは、mapを完全にロックするのではなく、対応するsegmentをロックします.これによって合併効率が向上しました.
構造関数の分析:
[java]view play copy print?
//*
これはコンカレントHashMapの無参画構造関数であり、デフォルトの大きさは16、負荷因子は0.75、同時レベルは16と見られます.
Put関数の分析:
[java]view play copy print?
//*
hash()関数によってkeyのハッシュ値が得られ、対応するsegmentが得られ、segmentによってEntityが格納されていることが分かる.
また、「再検出」(条件付きスレッド安全参照[2])などの合併問題を避けるために、ConcerenthashMapはputIfAbsent(K key,V value)を提供しています. 方法は、keyが存在しない場合に追加します.(keyの存在は二つの条件、一つはkeyのhashcode方法、もう一つはkeyのequal方法です.)
長所:対応するsegmentのため 全体のmapをロックするのではなく、ロックをかけて、合併性を高めました.挿入、検索、除去操作の伸縮性を直接高めることができます.
短所:mapの要素を遍歴するときは、全てのsegmentのロックを取得して、遍歴を使用すると遅くなります.ロックの増加は、システムのリソースを占有します.このセット全体を動作させるいくつかの方法(例えば、
size()
またはisEmpty()
)があります.これらの方法は多くのロックを一度に獲得することが必要であり、また不正な結果を返すリスクがあるからです.