4

私は LinkedHashMap を使用しており、環境はマルチスレッドであるため、この構造はスレッドセーフである必要があります。特定のイベント中に、db へのマップ プッシュ全体を読み取り、すべてをクリアする必要があります。

ほとんどの場合、このマップには書き込みのみが発生します。このマップのエントリ数は 50 に制限されています。

Oracle MAF を使用していますが、Collections.syncronizedMap を利用できません。それで、書き込みと読み取りが私に当たらないようにするために同期ブロックに入れる必要があるものは何ですか

いくつかの要件:

  1. 循環キューのように動作させる必要があるため、LinkedHashMap の removeEldestEntry メソッドをオーバーライドします。
  2. 順序を守る必要がある
4

3 に答える 3

3

それで、書き込みと読み取りが私に当たらないようにするために同期ブロックに入れる必要があるものは何ですか

すべてのメソッド呼び出しは同期ブロック内にある必要があります。

注意が必要なのは、Iterator の使用中です。Iterator の使用中はロックを保持する必要があります。例えば

// pre Java 5.0 code
synchronized(map) { // the lock has to be held for the whole loop.
    for(Iterator iter = map.entrySet().iterator(); iter.hashNext(); ) {
         Map.Entry entry = iter.next();
         String key = (String) entry.getKey();
         MyType value = (MyType) entry.getValue();
         // do something with key and value.
    }
}
于 2016-02-10T17:14:31.467 に答える
2

ほとんどのLinkedHashMap操作はsynchronizationマルチスレッド環境で必要であり、純粋に見えるものであってもget(key)get(key)実際にはいくつかの内部ノードを変更します。最も簡単にできるのは、 を使用することですCollections.synchronizedMap

Map<K,V> map = Collections.synchronizedMap(new LinkedHashMap<>());

利用できない場合は、簡単に追加できます。これは、すべての操作が単純なdecoratorマップにすぎないためです。synchronize

class SyncMap<T,U> implements Map<T,U>{
  SyncMap<T,U>(LinkedHashMap<T,U> map){
   ..
  }
  public synchronized U get(T t){
    ..
  }
}
于 2016-02-10T17:18:54.900 に答える
1

If you are using a java version 1.5 or newer you can use java.util.concurrent.ConcurrentHashMap.

This is the most efficient implementation of a Map to use in a multithread environment.

It adds also some method like putIfAbsent very useful for atomic operations on the map.

From java doc:

Retrieval operations (including get) generally do not block, so may overlap with update operations (including put and remove). Retrievals reflect the results of the most recently completed update operations holding upon their onset. For aggregate operations such as putAll and clear, concurrent retrievals may reflect insertion or removal of only some entries

So verify is this is the behaviour you expect from your class.


If your map has only 50 records and needs to be used as a circular Queue why you use a Map? Is not better to use one of the Queue implementations?


If you need to use a LinkedHashMap use the following:

Map m = Collections.synchronizedMap(new LinkedHashMap());

From javadoc of LinkedHashMap:

Note that this implementation is not synchronized. If multiple threads access a linked hash map concurrently, and at least one of the threads modifies the map structurally, it must be synchronized externally. This is typically accomplished by synchronizing on some object that naturally encapsulates the map. If no such object exists, the map should be "wrapped" using the Collections.synchronizedMap method. This is best done at creation time, to prevent accidental unsynchronized access to the map:

 Map m = Collections.synchronizedMap(new LinkedHashMap(...));

https://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashMap.html

于 2016-02-10T17:11:01.863 に答える