3


JavaでConcurrentHashMap、
特にputIfAbsentメソッドを見ると、このメソッドの一般的な使用法は次のようになります。

ConcurrentMap<String,Person>  map = new ConcurrentHashMap<>();
map.putIfAbsent("John",new Person("John"));

問題は、Personオブジェクトが常に初期化されることです。 ConcurrentHashMapの同様の動作を提供し、ファンクターまたはその他の手段を使用して値オブジェクトを構築する
ヘルパーコレクション(おそらくこれを提供するJavaフレームワーク) と構築コード(つまり、-functor.execute( ))は、マップに指定されたキーの値が含まれていない場合にのみ呼び出されますか?


4

1 に答える 1

2

これを行う唯一の方法は、ロックを使用することです。最初にチェックを使用することで、この影響を最小限に抑えることができます。

if(!map.containsKey("John"))
    synchronized(map) {
        if(!map.containsKey("John"))
           map.put("John", new Person("John"));
    }

ロックが必要な理由は、他のスレッドが同じオブジェクトを同時に追加しようとするのを防ぐために、Personを作成する間マップを保持する必要があるということです。ConcurrentMapは、このようなブロッキング操作を直接サポートしていません。

特定のキーへのロックを最小限に抑える必要がある場合は、次のようにすることができます。

ConcurrentMap<String, AtomicReference<Person>> map = new ConcurrentHashMap<String, AtomicReference<Person>>();

String name = "John";

AtomicReference<Person> personRef = map.get(name);
if (personRef == null)
    map.putIfAbsent(name, new AtomicReference<Person>());
personRef = map.get(name);
if (personRef.get() == null)
    synchronized (personRef) {
        if (personRef.get() == null)
            // can take a long time without blocking use of other keys.
            personRef.set(new Person(name));
    }
Person person = personRef.get();
于 2012-11-14T13:08:11.860 に答える