3

私はConcurrentMap < String、SomeObject >オブジェクトを持っています。 SomeObjectが存在する場合はそれを返すメソッドを作成するか、新しいSomeObjectを作成してマップに入れ、存在しない場合はそれを返します。必要に応じてキーを追加するときにConcurrentMapを同期する必要はありますか?

理想的には、ConcurrentMapのputIfAbsent(key, new SomeObject(key))を使用することができますが、そのたびに新しいSomeObject(キー)が作成されることになり、非常に無駄に思えます。

は、だから私は、次のコードに頼っが、それはこれを処理するための最良の方法だということを確認していない:

public SomeValue getSomevalue(String key){ 

    SomeValue result = concurrentMap.get(key); 

    if (result != null) 
    return result; 

    synchronized(concurrentMap){ 

    SomeValue result = concurrentMap.get(key); 

    if (result == null){ 
     result = new SomeValue(key); 
     concurrentMap.put(key, result); 
    } 

    return result; 
    } 
} 
+0

コードは正しいですが、同期ブロックにputIfAbsentを使用できます。より最適になるでしょう。 –

+0

@GuillaumeF。あなたはより最適な意味を説明できますか?その時点で、同期ブロック内でキーをチェックしてからヌル値を取得するため、キーがないことがわかります。 – isapir

+0

私は同期ブロック内のテストを削除することを意味します。あなたは既に同期の前にテストを行っているので、2回目のテストがnull以外の何かを返す確率は非常に低いです。 putIfAbsentをオブジェクトの新しいインスタンスに使用するのが最適なのは、まれにしか失敗しないためです。また、同期ブロックを完全に削除することもできます。 –

答えて

4

理想的には、私はのConcurrentMapのputIfAbsent(キー、新しいSomeObjectの(キー))を使用することができますしかし、それは毎回新しいSomeObject(キー)を作成することを意味し、非常に無駄に思える。

次にcomputeIfAbsentを使用:

concurrentMap.computeIfAbsent(key, SomeObject::new); 

のConcurrentMapと​​​​を使用ブロックの中央にマップに対して操作を実行することから、他のスレッドを妨げません。 ConcurrentMapは同期のためにマップのモニターを使用することを約束しておらず、ConcurrentHashMapとConcurrentSkipListMapはマップ・オブジェクト上で同期しません。

ConcurrentMapインターフェイスでは、値が1回だけ計算されること、またはキーが既に存在する場合に値が計算されないことを保証しないことに注意してください。 ConcurrentHashMapはこれらの約束をしますが、ConcurrentSkipListMapは行いません。

+0

非常に良い。私はこれがまさに私が探していたものだと思う:) – isapir

+0

明確化のためにありがとう。私は 'ConcurrentHashMap'を使用していますので、うまく動作します。 – isapir

+0

明確にするために、 'computeIfAbsent'がJava 1.8に追加されたので、Java 1.7のために私が投稿したコードは「行く方法」ですか? – isapir

関連する問題