2012-04-14 5 views
4

私は、アプリケーションの実行中に情報を格納するために使用されるプライベート静的マップを持つJavaクラスを持っています。キー/値をマップに一度だけ入れても、マップの値は何度も読み取られることがあります。Javaでスレッドセーフな追記型多値マップを作成するにはどうすればよいですか?

私は今それを持っているので、コードはgetとnullをチェックします。 nullの場合は、必要なデータを集めてマップに配置します。その後のクライアントコードによる呼び出しは、マップから値を取得することが保証されます。クライアントはヌルチェックを行う必要はありません。

これは、データを地図に入れるのはコストがかかるため、キーごとに1回しか実行したくないからです。

このパターンはありますか?私は、この状況について議論する何かを見つけることができないようです。あなたが保存して同期取得に必要なすべてを提供します

public class TestWorm { 

    private static Map<String, Object> map = new HashMap<String, Object>(32); 

    public Object getValue(String key) { 
     if (map.get(key) != null) { 
      return map.get(key); 
     } 

     // do some process to get Object 
     Object o = new Object(); 
     map.put(key, o); 
     return o; 
    } 
} 
+1

get()を実行すると、一度だけ行う必要があります。 ;) –

+0

@sprokeyboy:あなたが必要としているのはまさにGuavaの[LoadingCache](http://code.google.com/p/guava-libraries/wiki/CachesExplained)です。 – maaartinus

答えて

3

あなたの最善の策はConcurrentHashMapで、putIfAbsentメソッドです。

あなたの実装はスレッドセーフではありません。スレッドを安全にするには、フィールドfinalを宣言し、実装クラスをConcurrentHashMapに変更します。これで十分ですが、値が計算されて何度も保存されるかどうか気にしない場合(これはまれです。対応する値はまだ計算されていませんが、通常はキャッシュ内に何かがあるときに最も一般的な場合が多いため、通常は良いトレードオフですが、この場合は既存の値を取得するために余分な同期を使用しません)

指定されたキーに対してアプリケーションに最大で1つの値が存在することを確認したい場合は、putの代わりにputIfAbsentを使用して実装をさらに拡張できます。

グアバライブラリを使用することですこれを実装する別の方法:http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/MapMaker.html

ConcurrentHashMapV8のcomputeIfAbsent(http://gee.cs.oswego.edu/cgi-binを用いることであろうことを行うにはさらに別の方法/viewcvs.cgi/jsr166/src/jsr166/ConcurrentHashMapV8.java?view=markup)、いつかJava 8に現れます。

2

チェックアウトConcurrentHashMap.putIfAbsent()

TIA

はここで完全に非スレッドセーフな例です。

+1

ええputIfAbsentは、追加したいオブジェクトが高価でない場合は問題ありません。私がこれを行う必要がある理由は、毎回マップのオブジェクトを作成するために高価な作業をしなくてもいいということです。 – sproketboy

0

これは典型的なキャッシュパターンです。

Spring Framework offers a good API since 3.1

例えば

しかしEhcache等が専門的なフレームワークもあります。

+0

真剣に?基本的なパターンのために私のプロジェクトにフレームワークまたはライブラリ全体を追加する必要があると思いますか? – sproketboy

+0

@ダン・ハワード私はちょうどそのパターンがあなたの質問に答えようとしました。もちろん、小さなプロジェクトでは、フレームワークのメリットがありません。大規模なプロジェクト全体にマップアクセスが広がっているなら、ehcacheのようなフレームワークに入れてください。 – Omnaest

関連する問題