线程安全LinkedHashMap没有Collections.synchronized
我正在使用LinkedHashMap,并且环境是multithreading的,因此这个结构需要是线程安全的。 在特定事件期间,我需要读取整个地图推送到数据库并清除所有。
大多数时候只有写入发生在这张地图上。 此地图限制了50个条目。
我使用的是Oracle MAF,它没有Collections.syncronizedMap。 那么,我需要在synchronized块中放置什么东西以确保写入和读取不会遇到concurrentModificationException等
几个要求:
- 我需要像循环队列一样表现它,以便重写LinkedHashMap的removeEldestEntry方法。
- 我需要保留订单
那么,我需要在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