假设有以下场景:
某一个业务要求,定时的从数据库中取出一批数据放入一个hashmap
中。
有多个线程对这个Map
进行读操作。
每过一段时间(如3分钟),都会对这个Map
进行修改(put or remove
)
该场景对数据的一致性没有非常严格的要求。
如何能够在不使用同步的情况下,对这个Map
进行安全的操作呢?(例如不用concurrentHashMap
,或Collections.synchronizedMap
)
我的想法是,每次在需要修改Map
的时候,可以创建一个旧Map
的副本,对副本进行修改后,再替换原先的·Map·
例如:Map newMap = oldMap.clone();
//或者用new HashMap().putall(oldMap)
来创造副本newMap.put / remove ..... //修改map
oldMap = newMap;
//替换上去
这样就不会因为对同一个map的并发读写而导致快速迭代失败。有没有大神看看这样有什么潜在的问题,比如GC。请不吝赐教
(
jdk 1.6 api hashMap
在迭代器创建之后,如果从结构上对映射进行修改,除非通过迭代器本身的 remove 方法,其他任何时间任何方式的修改,迭代器都将抛出 ConcurrentModificationException。因此,面对并发的修改,迭代器很快就会完全失败,而不冒在将来不确定的时间发生任意不确定行为的风险。
)
尽量用同步,可以避免很多的问题,同步:
` synchronizedMap
public static Map synchronizedMap(Map m)`
返回由指定映射支持的同步(线程安全的)映射。为了保证按顺序访问,必须通过返回的映射完成 所有对底层实现映射的访问。
在返回映射的任意 collection 视图上进行迭代时,用户必须手工在返回的映射上进行同步:
Map m = Collections.synchronizedMap(new HashMap());
...
Set s = m.keySet(); // Needn't be in synchronized block
...
synchronized(m) { // Synchronizing on m, not s!
Iterator i = s.iterator(); // Must be in synchronized block
while (i.hasNext())
foo(i.next());
}
不遵从此建议将导致无法确定的行为。
如果指定映射是可序列化的,则返回的映射也将是可序列化的。
参数:
m - 被“包装”在同步映射中的映射。
返回:
指定映射的同步视图。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。