Java 并发容器之 CopyOnWriteArrayList

来源:互联网 发布:mac 远程连接 windows 编辑:程序博客网 时间:2024/06/07 15:40

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)数据一致性问题:只保证最终一致性,不能保证数据的实时一致性

作者:海子
    
出处:http://www.cnblogs.com/dolphin0520/
    
本博客中未标明转载的文章归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

0 0
原创粉丝点击