问题帖子--Concurrent Read/Write Map
DK1.5 引入了 concurrent package, 提供了更多的concurrent 控制方法。 还提供了一个 ConcurrentHashMap 类。从API上看,是可以读写同步。多个thread可以同时读取,一个thread写的时候,其他thread都不能读写。 这是一个用处很广、很方便的类。我想,能不能在 jdk1.4 及以下版本也提供一个。于是查看了 ConcurrentHashMap的代码。 我本以为,实现思路应该是用到了 ReadWriteLock. 大致是这样的思路。
Java代码
// my guess
class CocurrentHashMap
{
Private Map map = null;
final ReadWriteLock rwLock = new …. ;
final Lock readLock = rwLock.readLock();;
final Lock writeLock = rwLock.writeLock();;
// decorate the map as concurrent
public CocurrentHashMap(Map m);{
map = m;
}
// all write method, like put, putAll, remove, clear
public void putAll(Map m);{
writeLock.lock();;
try{
map.putAll(m);;
}finally{
writeLock.unlock();;
}
}
// all read method. like get, containsKey, containsValue, entrySet();
public Object get(Object key);{
readLock.lock();;
try{
return map.get(key);;
}finally{
readLock.unlock();;
}
};
// as we can see, in such places it is convenient to use AOP here. :-);
看了java 1.5 code,才知道不是这样。ConcurrentHashMap是一个比较复杂的类,自己实现了Lock。 不过也无妨,上面的思路很简单,我也可以找到 third party concurrent.jar, 按照上面自己的猜测思路为 jdk1.4 (and below) 写一个concurrent map. 这时候,我又想到。Read Lock也是lock。而某些情况下,只是初始化或者 refresh的时候,map 需要write,大多数情况下,都是 read。能不能继续减少 Read Lock 的 overhead? 我采取了这样一个思路。维护两个 map. 一个是 map to read, read only. 一个是 map to write, write only. 当用户使用 read method 的时候,就用 map to read ; 当用户使用 write method的时候,就写入到 map to write,之后还要copy 一份map to write ,然后把这个copy 赋给map to read。 所以,read 的时候,非常快,几乎没有 overhead。而write的时候,非常 expensive, 每次write完之后,都要 copy 一遍。所以,建议尽量使用 putAll() method。 这个思路还有一点不利,就是 同时维护两个同样的entry 的 map. 空间上的效率不是很好,虽然,key, value pair都是object reference, 但map 的entry set结构要有两份。 代码如下。为了效率,没有用AOP。:-)
Java代码
/*
* Read Write Map
*
* Write is expensive.
* Read is fast as pure HashMap.
*
* Note: extra info is removed for free use
*/
package net.sf.map;
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 = Collections.unmodifiableMap(getNewMap(););;
protected final Map mapToWrite = Collections.synchronizedMap(getNewMap(););;
// you can override it as new TreeMap();;
protected Map getNewMap();{
return new HashMap();;
}
// copy mapToWrite to mapToRead
protected void sync();{
Map newMapToRead = getNewMap();;
newMapToRead.putAll(mapToWrite);;
mapToRead = Collections.unmodifiableMap(newMapToRead);;
}
// 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 void clear(); {
mapToWrite.clear();;
sync();;
}
public Object remove(Object key); {
Object o = mapToWrite.remove(key);;
sync();;
return o;
}
public Object put(Object key, Object value); {
Object o = mapToWrite.put(key, value);;
sync();;
return o;
}
public void putAll(Map t); {
mapToWrite.putAll(t);;
sync();;
}
}
希望这段代码能够帮助 有类似需求的人。
- C++服务器开发之基于对象的编程风格
- The jQuery UI CSS Framework
- hadoop:将WordCount打包成独立运行的jar包
- Hadoop: MapReduce2多个job串行处理
- UE4新手引导之下载和安装虚幻4游戏引擎
- mac 下卸载mysql的方法
- ZooKeeper 笔记(1) 安装部署及hello world
- mybatis 使用经验小结
- ZooKeeper 笔记(2) 监听数据变化
- 使用C# 和Consul进行分布式系统协调
- 设置 java -jar 的进程显示名称
- 爱浪携手豆瓣内容、腾讯共同发布AI语音耳机
- Win.ini和注册表的读取写入
- ZooKeeper 笔记(4) 实战应用之【消除单点故障】
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- laravel5.0在linux下解决.htaccess无效和去除index.php的问题
- laravel返回统一格式错误码问题
- 使用 PHP Masked Package 屏蔽敏感数据的实现方法
- PHP简单实现图片格式转换(jpg转png,gif转png等)
- 在thinkphp5.0路径中实现去除index.php的方式
- Laravel5.5 手动分页和自定义分页样式的简单实现
- laravel自定义分页的实现案例offset()和limit()
- Laravel6.0.4中将添加计划任务事件的方法步骤
- Laravel 不同生产环境服务器的判断实践
- 解决thinkPHP 5 nginx 部署时,只跳转首页的问题
- Laravel 类和接口注入相关的代码
- laravel unique验证、确认密码confirmed验证以及密码修改验证的方法
- laravel 如何实现引入自己的函数或类库
- PHP实现15位身份证号转18位的方法分析
- Yii框架的redis命令使用方法简单示例