CopyOnWriteArrayList

一、简介

    JDK5中添加了新的concurrent包,其中包含了很多并发容器,这些容器针对多线程环境进行了优化,大大提高了容器类在并发环境下的执行效率。

    CopyOnWriteArrayList类是一个线程安全的List接口的实现,在该类的内部进行元素的写操作时,底层的数组将被完整的复制,这对于读操作远远多于写操作的应用非常适合。在CopyOnWriteArrayList上进行操作时,读操作不需要加锁,而写操作类实现中对其进行了加锁。

二、具体实现

    CopyOnWriteArrayList底层的定义如下:

Java代码   收藏代码
  1. public class CopyOnWriteArrayList<E>  
  2.         implements List<E>, RandomAccess, Cloneable, java.io.Serializable {  
  3.   
  4.     private volatile transient E[] array;  
  5.   
  6.     private E[] array() { return array; }  
  7.   
  8.     // 该操作是加锁的,防止array在copy的时候被替换   
  9.     private synchronized void copyIn(E[] toCopyIn, int first, int n) {  
  10.         array  = (E[]) new Object[n];  
  11.         System.arraycopy(toCopyIn, first, array, 0, n);  
  12.     }  
  13.   
  14.   ...  
  15. }  

    读写操作:

Java代码   收藏代码
  1. public class CopyOnWriteArrayList<E>  
  2.         implements List<E>, RandomAccess, Cloneable, java.io.Serializable {  
  3.   
  4.     public E get(int index) {  
  5.      // 由于包括rangeCheck和index两个操作,并不是直接在array上执行  
  6.    // 而是使用本地变量elementData引用array数组,防止两个操作之间  
  7.    // array被替换  
  8.      E[] elementData = array();  
  9.         rangeCheck(index, elementData.length);  
  10.         return elementData[index];  
  11.     }  
  12.       
  13.     public synchronized E set(int index, E element) { // 是同步的  
  14.         int len = array.length;  
  15.         rangeCheck(index, len);  
  16.         E oldValue = array[index];  
  17.   
  18.         // 判断该写的元素与原数据是否相同  
  19.         boolean same = (oldValue == element ||  
  20.         (element != null && element.equals(oldValue)));  
  21.           
  22.         if (!same) {  
  23.             // [1] 创建一个新数组,将原array的值拷贝至新数组  
  24.         E[] newArray = (E[]) new Object[len];  
  25.             System.arraycopy(array, 0, newArray, 0, len);  
  26.             // [2] set的元素  
  27.         newArray[index] = element;  
  28.             // [3] 替换底层array数组  
  29.         array = newArray;  
  30.         }  
  31.         return oldValue;  
  32.     }  
  33.   
  34.   ...  
  35. }  

    add和remove也采用相同的技术:

Java代码   收藏代码
  1. public class CopyOnWriteArrayList<E>  
  2.         implements List<E>, RandomAccess, Cloneable, java.io.Serializable {  
  3.   
  4.     public synchronized boolean add(E element) {  
  5.         // [1] new and copy  
  6.         int len = array.length;  
  7.         E[] newArray = (E[]) new Object[len+1];  
  8.         System.arraycopy(array, 0, newArray, 0, len);  
  9.         // [2] add element  
  10.         newArray[len] = element;  
  11.         // [3] change base array  
  12.         array = newArray;  
  13.         return true;  
  14.     }  
  15.   
  16.     public synchronized E remove(int index) {  
  17.         int len = array.length;  
  18.         rangeCheck(index, len);  
  19.         E oldValue = array[index];  
  20.         // new一个新的数组  
  21.       E[] newArray = (E[]) new Object[len-1];  
  22.         // copy index之前的元素  
  23.       System.arraycopy(array, 0, newArray, 0, index);  
  24.         // copy余下的元素  
  25.       int numMoved = len - index - 1;  
  26.         if (numMoved > 0)  
  27.             System.arraycopy(array, index+1, newArray, index, numMoved);  
  28.         // 替换array引用      
  29.      array = newArray;  
  30.         return oldValue;  
  31.     }  
  32.   
  33.   ...  
  34. }  

   特别注意:在CopyOnWriteArrayList上获得的Iterator是不能进行set和remove操作的,否则会抛出异常。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CopyOnWriteArrayList是一个线程安全的List实现,它通过每次修改操作(添加、删除、修改)时都创建一个新的底层数组来实现线程安全性。 CopyOnWriteArrayList的特点如下: 1. 线程安全:多个线程可以同时读取CopyOnWriteArrayList的内容,而不需要额外的同步机制。这使得它非常适合在读操作远远多于写操作的场景中使用。 2. 写操作的代价较高:每次对CopyOnWriteArrayList进行写操作时,都会创建一个新的底层数组,因此写操作的代价较高。 3. 实时性较低:由于写操作会创建新的底层数组,读取操作可能会看到旧的数据,因此CopyOnWriteArrayList的实时性较低。 使用CopyOnWriteArrayList的示例代码如下: ```java import java.util.concurrent.CopyOnWriteArrayList; public class Main { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); list.add("Hello"); list.add("World"); for (String item : list) { System.out.println(item); } } } ``` 在上述代码中,我们创建了一个CopyOnWriteArrayList,并向其中添加了两个元素。然后使用增强for循环遍历CopyOnWriteArrayList中的元素,并打印输出。 需要注意的是,CopyOnWriteArrayList适用于读操作远远多于写操作的场景,如果写操作非常频繁,可能会导致性能问题。此外,CopyOnWriteArrayList不保证元素的顺序性,因为在写操作时会创建新的底层数组。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值