Pet*_*Lee 50 java data-structures
我需要一个LinkedHashMap的数据结构,并且是线程安全的.
我怎样才能做到这一点 ?
Yis*_*hai 29
您可以将地图包装在Collections.synchronizedMap中以获取维护插入顺序的同步散列映射.这不如ConcurrentHashMap有效(并且不实现ConcurrentMap的额外接口方法),但它确实为您提供了(某种程度上)线程安全的行为.
即使是强大的Google Collections似乎也没有解决这个特殊问题.但是,有一个项目确实试图解决这个问题.
我在某种程度上说同步,因为在并发修改异常可能发生的意义上,迭代仍然不是线程安全的.
hoh*_*uli 14
这个问题有很多不同的方法.你可以使用:
Collections.synchronizedMap(new LinkedHashMap());
Run Code Online (Sandbox Code Playgroud)
正如其他回复所暗示的那样,但这有几个问题你需要注意.最值得注意的是,在迭代集合时,您经常需要保持集合同步锁定,这反过来又会阻止其他线程访问集合,直到您完成对它的迭代.(参见Java理论与实践:并发集合类).例如:
synchronized(map) {
for (Object obj: map) {
// Do work here
}
}
Run Code Online (Sandbox Code Playgroud)
运用
new ConcurrentHashMap();
Run Code Online (Sandbox Code Playgroud)
可能是一个更好的选择,因为您不需要锁定集合来迭代它.
最后,您可能想要考虑更具功能性的编程方法.那就是你可以认为地图本质上是不可变的.您可以创建一个包含旧地图内容和新添加内容的新地图,而不是添加到现有地图.这听起来很奇怪,但它实际上是Scala处理并发和集合的方式
小智 7
您可以使用ConcurrentSkipListMap,仅在Java SE/EE 6或更高版本中可用.它是预先订购的,因为按键按照它们的自然顺序排序.您需要有一个比较器或使键可比对象.为了模仿链接的哈希映射行为(迭代顺序是添加条目的时间顺序),我实现了我的密钥对象总是比较大于给定的其他对象,除非它是相等的(无论你的对象是什么) ).包装的同步链接哈希映射是不够的,因为如 http://www.ibm.com/developerworks/java/library/j-jtp07233.html中所述:"同步集合包装器,synchronizedMap和synchronizedList有时称为条件线程-safe - 所有单个操作都是线程安全的,但控制流依赖于先前操作结果的操作序列可能会受到数据竞争的影响.清单1中的第一个代码段显示了常见的put-if-absent惯用语 - - 如果Map中还没有条目,请添加它.不幸的是,正如所写的那样,另一个线程可能在containsKey()方法返回的时间和put()之间插入一个具有相同键的值.调用方法.如果要确保一次插入一次,则需要使用在Map m上同步的synchronized块包装这对语句."
所以唯一有帮助的是ConcurrentSkipListMap,它比普通的ConcurrentHashMap慢3-5倍.
Collections.synchronizedMap(new LinkedHashMap())