Java学习笔记(5)
CopyOnWriteArrayList
- Copy-On-Write:简称COW,是一种程序设计中的优化策略。
- COW基本思路:一开始大家都在共享同一个内容,当某个人想要修改这个内容时,才会真正把内容Copy出去形成一个新的内容然后再改,这是一种延时懒惰策略
- 使用COW机制的并发容器:CopyOnWriteArrayList和CopyOnWriteArraySet
- CopyOnWriteArrayList的add方法:
- 添加元素的时候是需要加锁的,否则多线程写的时候会Copy出N个副本出来
- /**
- * Appends the specified element to the end of this list.
- *
- * @param e element to be appended to this list
- * @return <tt>true</tt> (as specified by {@link Collection#add})
- */
- public boolean add(E e) {
- final ReentrantLock lock = this.lock;
- lock.lock();
- try {
- Object[] elements = getArray();
- int len = elements.length;
- Object[] newElements = Arrays.copyOf(elements, len + 1);
- newElements[len] = e;
- setArray(newElements);
- return true;
- } finally {
- lock.unlock();
- }
- }
- 读的时候不需要加锁,如果读的时候有多个线程正在向CopyOnWriteArrayList添加数据,读还是会读到旧的数据,因为写的时候不会锁住旧的CopyOnWriteArrayList
- public E get(int index) {
- return get(getArray(), index);
- }
- JDK中没有提供CopyOnWriteMap,我们可以参考CopyOnWriteArrayList来实现一个:
- import java.util.Collection;
- import java.util.Map;
- import java.util.Set;
- public class CopyOnWriteMap<K, V> implements Map<K, V>, Cloneable {
- private volatile Map<K, V> internalMap;
- public CopyOnWriteMap() {
- internalMap = new HashMap<K, V>();
- }
- public V put(K key, V value) {
- synchronized (this) {
- Map<K, V> newMap = new HashMap<K, V>(internalMap);
- V val = newMap.put(key, value);
- internalMap = newMap;
- return val;
- }
- }
- public V get(Object key) {
- return internalMap.get(key);
- }
- public void putAll(Map<? extends K, ? extends V> newData) {
- synchronized (this) {
- Map<K, V> newMap = new HashMap<K, V>(internalMap);
- newMap.putAll(newData);
- internalMap = newMap;
- }
- }
- }
- CopyOnWrite的应用场景:常用于读多写少的并发场景
- 使用注意事项:1)减少扩容开销
- 2)使用批量添加。因为每次添加,容器都会进行复制,所以减少添加次数,可以减少容器的复制次数。
- CopyOnWrite容器的缺点:
- 1)内存占用问题
- 2)数据一致性问题:只保证最终一致性,不能保证数据的实时一致性