jdk1.5以上的版本提供了CopyOnWriteArrayList、CopyOnWriteArraySet两个并发容器,其实现主要是将旧数据拷贝到新集合中做更改,然后直接将引用指向新集合。这两个类主要适用于读多写少的场景,有点类似于某些缓存更新策略。但是对于Map接口并没有相关实现。
关于自定义的CopyOnWriteMap和ConcurrentHashMap类的对比,后续有机会再具体分析。
以下是具体实现:
package com.caiya.test._concurrent;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.locks.ReentrantLock;
/**
* Created by caiya on 16/4/1.
*/
public class CopyOnWriteMap<K,V> implements Map<K,V>, Cloneable, Serializable {
private static final long serialVersionUID = -9220483591710681826L;
transient final ReentrantLock lock = new ReentrantLock();
private volatile transient Map<K,V> map;
public void setMap(Map<K, V> map) {
this.map = map;
}
public Map<K, V> getMap() {
return map;
}
public CopyOnWriteMap(){
map = new HashMap<K, V>();
}
public int size() {
return getMap().size();
}
public boolean isEmpty() {
return getMap().isEmpty();
}
public boolean containsKey(Object key) {
return getMap().containsKey(key);
}
public boolean containsValue(Object value) {
return getMap().containsValue(value);
}
public V get(Object key) {
return getMap().get(key);
}
public V put(K key, V value) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Map<K,V> newMap = new HashMap<K, V>(map);
V val = newMap.put(key, value);
map = newMap;
return val;
} finally {
lock.unlock();
}
}
public V remove(Object key) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Map<K,V> newMap = new HashMap<K, V>(map);
V val = newMap.remove(key);
map = newMap;
return val;
}finally {
lock.unlock();
}
}
public void putAll(Map<? extends K, ? extends V> m) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Map<K,V> newMap = new HashMap<K, V>(map);
newMap.putAll(m);
map = newMap;
} finally {
lock.unlock();
}
}
public void clear() {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Map<K,V> newMap = new HashMap<K, V>();
map = newMap;
} finally {
lock.unlock();
}
}
public Set<K> keySet() {
return getMap().keySet();
}
public Collection<V> values() {
return getMap().values();
}
public Set<Entry<K, V>> entrySet() {
return getMap().entrySet();
}
}