@22221cjp
2016-10-26T04:24:54.000000Z
字数 1934
阅读 1246
技术
CopyOnWrite 顾名思义就是写时拷贝,具体过程是对容器进行操作的时候,先将容器拷贝一份(浅拷贝),然后对容器进行添加元素,删除等。最后将原来容器的引用改为新的容器。
本质是一种“读写分离”的思想。
JDK提供了两种CopyOnWrite容器:CopyOnWriteArrayList和CopyOnWriteArraySet
但是我们根据需要,也可以自己实现其他的容器的CopyOnWrite版本。比如CopyOnWriteMap,代码如下:
package com.charles.work;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* 功能描述: 实现一个copy on write map,这是线程安全的,写时拷贝<p>
*
* @author : jinpeng.chen <p>
* @version 1.0 2016-10-24
* @since myworkspace 1.0
*/
public class CopyOnWriteMap<k, v> implements Map<k, v>, Cloneable {
private volatile Map<k,v> internalMap;
public CopyOnWriteMap() {
this.internalMap = new HashMap<k, v>();
}
@Override
public int size() {
return internalMap.size();
}
@Override
public boolean isEmpty() {
return internalMap.isEmpty();
}
@Override
public boolean containsKey(Object key) {
return internalMap.containsKey(key);
}
@Override
public boolean containsValue(Object value) {
return internalMap.containsValue(value);
}
@Override
public v get(Object key) {
return internalMap.get(key);
}
@Override
public v put(k key, v value) {
synchronized (this) {
Map<k, v> map = new HashMap<k, v>(internalMap);//copy
v val = map.put(key, value);
internalMap = map;
return val;
}
}
@Override
public v remove(Object key) {
synchronized (this) {
Map<k, v> map = new HashMap<k, v>(internalMap);
v remove = map.remove(key);
internalMap = map;
return remove;
}
}
@Override
public void putAll(Map<? extends k, ? extends v> m) {
synchronized (this) {
Map<k, v> map = new HashMap<k, v>(internalMap);
map.putAll(m);
internalMap=map;
}
}
@Override
public void clear() {
synchronized (this) {
internalMap = new HashMap<k, v>();
}
}
@Override
public Set<k> keySet() {
return internalMap.keySet();
}
@Override
public Collection<v> values() {
return internalMap.values();
}
@Override
public Set<Entry<k, v>> entrySet() {
return internalMap.entrySet();
}
}
需要注意:
减少扩容开销。根据实际需要,初始化CopyOnWriteMap的大小,避免写时CopyOnWriteMap扩容的开销。
使用批量添加。因为每次添加,容器每次都会进行复制,所以减少添加次数,可以减少容器的复制次数。
CopyOnWrite优点:
速度快,写的过程也不影响读
CopyOnWrite缺点:
读写不能实现实时一致性,但是保证最终一致性,如果要保证写完后立即能读到,不要用
每次写都需要拷贝,占用内存。且有性能消耗
试用场景:
读多写少的场景
尽量减少写操作,如果要写,也可以合并写操作,改为批量写