Java 不带集合的线程安全LinkedHashMap.synchronized
我使用的是LinkedHashMap,环境是多线程的,所以这个结构需要是线程安全的。在特定的事件中,我需要读取整个地图并将其推送到db并清除所有 大多数情况下,仅写入此映射。此地图最多有50个条目 我使用的是Oracle MAF,它没有Collections.syncronizedMap可用。那么,我需要在同步块中放入哪些内容来确保写入和读取不会影响我的concurrentModificationException等 几项要求:Java 不带集合的线程安全LinkedHashMap.synchronized,java,multithreading,data-structures,concurrency,oracle-maf,Java,Multithreading,Data Structures,Concurrency,Oracle Maf,我使用的是LinkedHashMap,环境是多线程的,所以这个结构需要是线程安全的。在特定的事件中,我需要读取整个地图并将其推送到db并清除所有 大多数情况下,仅写入此映射。此地图最多有50个条目 我使用的是Oracle MAF,它没有Collections.syncronizedMap可用。那么,我需要在同步块中放入哪些内容来确保写入和读取不会影响我的concurrentModificationException等 几项要求: 我需要将其表现为循环队列,以便覆盖LinkedHashMap的Re
如果您使用的是java 1.5版或更高版本,则可以使用 这是在多线程环境中使用的映射的最有效实现 它还添加了一些方法,如
putIfAbsent
对地图上的原子操作非常有用
从java文档:
检索操作(包括get)通常不会阻止,因此可能
与更新操作重叠(包括放置和删除)。检索
反映最近完成的更新操作的结果
坚持他们的开始用于聚合操作如putAll和
清除,并发检索可能只反映插入或删除
一些条目
因此,请确认这是您期望从您的类中获得的行为
如果您的地图只有50条记录,并且需要用作循环队列,为什么要使用地图?使用其中一个队列实现不是更好吗
如果需要使用LinkedHashMap,请使用以下选项:
Map m = Collections.synchronizedMap(new LinkedHashMap());
从LinkedHashMap的
请注意,此实现是不同步的。如果有多个线程
同时访问链接的哈希映射,并至少访问其中一个线程
如果从结构上修改贴图,则必须从外部对其进行同步。
这通常是通过在某个
自然地封装了地图。如果不存在这样的对象,则映射
应使用Collections.synchronizedMap方法“包装”。这
最好在创建时执行,以防止意外的不同步
访问地图:
Map m = Collections.synchronizedMap(new LinkedHashMap(...));
那么,我需要在同步块中放入哪些内容来确保写入和读取不会影响我的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.
}
}
在多线程环境中,大多数
LinkedHashMap
操作都需要同步
,即使是那些看起来纯粹像get(key)
,get(key)
的操作实际上也会变异一些内部节点。最简单的方法是使用Collections.synchronizedMap
Map<K,V> map = Collections.synchronizedMap(new LinkedHashMap<>());
每次在hasmap上调用一个方法时,比如
get
或put
,都需要用同步来围绕它。如果一行中有多个呼叫,可以用一次同步将它们全部包围起来。发布一些代码。在写入db时不要同步映射。制作一个副本(在synchronized{})中,将副本写入db。您看到了什么好处?我的地图最多可以容纳50个条目。我相信创建副本所需的时间与在副本上进行迭代所需的时间相同。因此,我的迭代方式类似于(diagMap!=null&&diagMap.size()>0){Set keys=diagMap.keySet();for(Date key:keys){String value=diagMap.get(key);dPath.append(key).append(DELIM).append(value);}}}它不会在for循环之后释放迭代器吗?我相信它不支持重写RemoveEdestEntry方法以使其行为像我在帖子中所说的循环队列一样,我的env中没有Collections.synchronizedMap,它使用受限的jdk配置文件,因此我认为您只能使用synchronized或使用自定义数据结构来包围代码。我需要为所有LinkedHashMap操作都这样做吗?好的,我认为最好在Get和puts周围使用synchronized块
class SyncMap<T,U> implements Map<T,U>{
SyncMap<T,U>(LinkedHashMap<T,U> map){
..
}
public synchronized U get(T t){
..
}
}