线程安全LinkedHashMap没有Collections.synchronized

我正在使用LinkedHashMap,并且环境是multithreading的,因此这个结构需要是线程安全的。 在特定事件期间,我需要读取整个地图推送到数据库并清除所有。

大多数时候只有写入发生在这张地图上。 此地图限制了50个条目。

我使用的是Oracle MAF,它没有Collections.syncronizedMap。 那么,我需要在synchronized块中放置什么东西以确保写入和读取不会遇到concurrentModificationException等

几个要求:

  1. 我需要像循环队列一样表现它,以便重写LinkedHashMap的removeEldestEntry方法。
  2. 我需要保留订单

那么,我需要在synchronized块中放置什么东西以确保写入和读取不会遇到concurrentModificationException等

Everything方法调用应该在同步块中。

棘手的是使用迭代器,因为你必须在迭代器的生命周期中持有锁。 例如

 // 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. } } 

大多数LinkedHashMap操作需要在multithreading环境中进行synchronization ,即使是看起来像get(key)get(key)实际上也会改变一些内部节点。 最简单的方法是使用Collections.synchronizedMap

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

现在,如果它不可用,您可以轻松添加它,因为它只是一个简单的decorator周围的地图, synchronize所有操作。

 class SyncMap implements Map{ SyncMap(LinkedHashMap map){ .. } public synchronized U get(T t){ .. } } 

如果您使用的是java 1.5或更高版本,则可以使用java.util.concurrent.ConcurrentHashMap

这是在multithreading环境中使用的Map的最有效实现。

它还添加了一些方法,如putIfAbsent对地图上的primefaces操作非常有用。

来自java doc:

检索操作(包括get) 通常不会阻塞 ,因此可能与更新操作(包括put和remove)重叠。 检索反映了最近完成的更新操作的结果。 对于诸如putAll和clear之类的聚合操作并发检索可能反映 插入或删除 某些条目

因此,validation这是您对class级的期望。


如果您的地图只有50条记录并且需要用作循环队列,为什么要使用地图? 使用其中一个Queue实现不是更好吗?


如果需要使用LinkedHashMap,请使用以下命令:

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

LinkedHashMap javadoc :

请注意,此实现不同步。 如果多个线程同时访问链接的哈希映射,并且至少有一个线程在结构上修改了映射,则必须在外部进行同步。 这通常通过在自然封装地图的某个对象上进行同步来实现。 如果不存在此类对象,则应使用Collections.synchronizedMap方法“包装”该映射。 这最好在创建时完成,以防止意外地不同步访问地图:

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

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