4

アプリケーションの実行中に情報を格納するために使用されるプライベート静的マップを持つ Java クラスがあります。キー/値を Map に入れるのは 1 回だけですが、マップの値は何度も読み取られる可能性があります。

したがって、私が今持っている方法では、コードは get を実行し、null をチェックします。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; 
    }
}
4

3 に答える 3

3

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

あなたの実装はスレッドセーフではありません。スレッド セーフにするには、フィールド final を宣言し、実装クラスを ConcurrentHashMap に変更します。これで十分です。値が計算されて数回格納されることを気にしない場合は、これで十分です (これはまれです。2 つのスレッドが同時に get と get を入力する場合)。対応する値はまだ計算されていません. これは通常良いトレードオフです. 通常最も一般的なケースはキャッシュに何かがある場合です. そしてこの場合, 既存の値を取得するために余分な同期を使用しません.)

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

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

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

于 2012-04-14T10:14:18.710 に答える
2

ConcurrentHashMap.putIfAbsent()同期的に保存および取得するために必要なすべてを提供するチェックアウト。

于 2012-04-14T10:10:20.230 に答える
0

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

たとえば、SpringFrameworkは3.1以降の優れたAPIを提供します

しかし、Ehcacheのような特殊なフレームワークもあります。

于 2012-04-14T10:17:42.750 に答える