用一个Map存放常用的Object,这个Map的并发读取的频率很高,而写入的频率很低,一般只在初始化、或重新装装载的时候写入。读写冲突虽然很少发生,不过一旦发生,Map的内部结构就可能乱掉,所以,我们不得不为Map加上同步锁。
我们可以采用Copy On Write的机制,来加强Map的读取速度。
Copy On Write是这样一种机制。当我们读取共享数据的时候,直接读取,不需要同步。当我们修改数据的时候,我们就把当前数据Copy一份副本,然后在这个副本上进行修改,完成之后,再用修改后的副本,替换掉原来的数据。这种方法就叫做Copy On Write。
Oracle等关系数据库的数据修改就采用Copy On Write的模式。Copy On Write模式对并发读取的支持很好,但是在并发修改的时候,会有版本冲突的问题。可能有多个线程同时修改同一份数据,那么就同时存在多个修改副本,这多个修改副本可能会相互覆盖,导致修改丢失。因此,Oracle等数据库通常会引入版本检查机制。即增加一个版本号字段,来检测是否存在并发修改。相似的版本控制机制存在于CVS、SVN等版本控制工具中。
在我们的Copy On Write Map中,我们只需要让新数据覆盖旧数据就可以了,因此不需要考虑版本控制的问题。这就大大简化了我们的实现。
基本思路就是让读和写操作分别在不同的Map上进行,每次写完之后,再把两个Map同步。代码如下:
/*
* Copy On Write Map
*
* Write is expensive.
* Read is fast as pure HashMap.
*
* Note: extra info is removed for free use
*/
import java.lang.Compiler;
import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.HashMap;
import java.util.Collections;
public class ReadWriteMap implements Map {
protected volatile Map mapToRead = getNewMap();
// you can override it as new TreeMap();
protected Map getNewMap(){
return new HashMap();
}
// copy mapToWrite to mapToRead
protected Map copy(){
Map newMap = getNewMap();
newMap.putAll(mapToRead);
return newMap;
}
// read methods
public int size() {
return mapToRead.size();
}
public boolean isEmpty() {
return mapToRead.isEmpty();
}
public boolean containsKey(Object key) {
return mapToRead.containsKey(key);
}
public boolean containsValue(Object value) {
return mapToRead.containsValue(value);
}
public Collection values() {
return mapToRead.values();
}
public Set entrySet() {
return mapToRead.entrySet();
}
public Set keySet() {
return mapToRead.keySet();
}
public Object get(Object key) {
return mapToRead.get(key);
}
// write methods
public synchronized void clear() {
mapToRead = getNewMap();
}
public synchronized Object remove(Object key) {
Map map = copy();
Object o = map.remove(key);
mapToRead = map;
return o;
}
public synchronized Object put(Object key, Object value) {
Map map = copy();
Object o = map.put(key, value);
mapToRead = map;
return o;
}
public synchronized void putAll(Map t) {
Map map = copy();
map.putAll(t);
mapToRead = map;
}
}
这个Map读取的时候,和普通的HashMap一样快。
写的时候,先把内部Map复制一份,然后在这个备份上进行修改,改完之后,再让内部Map等于这个修改后的Map。这个方法是同步保护的,避免了同时写操作。可见,写的时候,开销相当大。尽量使用 putAll() method。
分享到:
相关推荐
基于HashMap的学生管理系统
基于HashMap的用户标签处理兼Java中HashMap实现原理研究
从一个公司的项目中提取的一个基于共享内存的hashMap,vector,list等的相关实现,应用与游戏服务器的数据保存与访问
比较Java原生的 3种Map的效率。 1. TreeMap 2. HashMap 3. ConcurrentSkipListMap 本测试查找方法使用Map的get方法,循环、离散获取。... SkipListMap的范围查询效率比HashMap和TreeMap效率都要高。
首先会将传入的可以、做hash运算计算出...由于数组的长度有限,所以难免出现不同放入key通过运算得到的index相同,这种情况可以利用链表来解决,HashMap会在table[index]出形成链表,采用头插法将数据插入链表中
《java编程思想》,Map结合HashMap获取键相关联的值
易语言HashMap类源码,HashMap类,初始设置,加入,取值,删除,清空,取所有键,取所有值,枚举所有键,键总数,是否为空,是否存在键,取所有键值对,计算散列值,更新阈值,计算索引,重新索引
JNI处理hashmap,string等对象的操作,别处绝对没有的
用数据结构的思想实现java中的类hashmap
Map,HashMap,TreeMap的使用 很详细额,值得看看
理解面向对象后的代码抽取,HashMap的二次封装,总之目的减少点代码工作量,见代码示例
一个用于js里面 用javascript实现的HashMap类
结合Java的HashMap中的一些优点,改进了C++ 的hash_map。 详细说明见我的博客:http://blog.csdn.net/mdj67887500/article/details/6907702
HashMap存放.doc
hashMap基本工作原理,图解分析,基础Map集合
老外的开源代码,好用,收藏了。
用hashmap结构将字典文件中的词条装入内存,并基于该结构进行查询
NULL 博文链接:https://mox-sir.iteye.com/blog/2124644
jsp上使用object[]看不懂吧?写vo太烦琐了?ok,都交给map吧、本工具类的使命就是让map代替所有的vo,让编程变得更美好。 附有详细的使用例子。 java精英团队十年编程精华。
下面小编就为大家带来一篇基于HashMap遍历和使用方法(详解)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧