线程安全的LinkedHashMap没有Collections.synchronized

时间:2016-02-10 17:05:09

标签: java multithreading data-structures concurrency oracle-maf

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

大部分时间只会写入此地图。此地图限制了50个条目。

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

几个要求:

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

3 个答案:

答案 0 :(得分:3)

  

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

所有方法调用都应该在同步块中。

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

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

答案 1 :(得分:1)

在多线程环境中,大多数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){
    ..
  }
}

答案 2 :(得分:0)

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

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

它还添加了一些像putIfAbsent这样的方法,对地图上的原子操作非常有用。

来自java doc:

  

检索操作(包括get)一般不阻止,所以可能   与更新操作重叠(包括put和remove)。检索   反映最近完成的更新操作的结果   坚持他们的发作。 适用于汇总操作,例如putAll和   明确并发检索可能反映了 的插入或删除   一些条目

因此,验证这是您对班级的期望。

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

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

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

来自LinkedHashMap的{​​{3}}:

  

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

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

javadoc