java併發之CopyOnWriteArrayList

541732025發表於2014-04-01

CopyOnWriteArrayList是執行緒安全的、並且讀操作無鎖的ArrayList。
不像ArrayList預設初始化大小為10的Object[],CopyOnWriteArrayList預設初始化大小為0的Object[]
1,add(E)
add方法沒有給整個方法加synchronized關鍵字,而是使用ReentrantLock來保證執行緒安全。
該方法和ArrayList的add方法不同,ArrayList在add時候如果List中元素個數超出Object[]大小,則擴容,預設擴容1.5倍,而CopyOnWriteArrayList是新建立一個比原來大1的陣列,然後將新元素放在最後。

2,remove(E)

在ArrayList的remove方法中,程式碼如下:

點選(此處)摺疊或開啟

  1. public E remove(int index) {
  2. ...
  3. E oldValue = (E) elementData[index];
  4. int numMoved = size - index - 1;
  5. if (numMoved > 0)
  6.    System.arraycopy(elementData, index+1, elementData, index,
  7.     numMoved);
  8. elementData[--size] = null; // Let gc do its work
  9. return oldValue;
  10. }

從程式碼可以看出,ArrayList是直接操作原陣列,利用 System.arraycopy將index之後的元素往前挪。
而在CopyOnWriteArrayList的remove中,和add方法一樣,也是透過ReentrantLock保證執行緒安全,程式碼如下:

點選(此處)摺疊或開啟

  1. public E remove(int index) {
  2. final ReentrantLock lock = this.lock;
  3. lock.lock();
  4. try {
  5.    Object[] elements = getArray();
  6.    int len = elements.length;
  7.    Object oldValue = elements[index];
  8.    int numMoved = len - index - 1;
  9.    if (numMoved == 0)
  10.         setArray(Arrays.copyOf(elements, len - 1));
  11.    else {
  12.         Object[] newElements = new Object[len - 1];
  13.         System.arraycopy(elements, 0, newElements, 0, index);
  14.         System.arraycopy(elements, index + 1, newElements, index,numMoved);
  15.         setArray(newElements);
  16.    }
  17.    return (E)oldValue;
  18. } finally {
  19.    lock.unlock();
  20. }
  21.     }

從程式碼可以看出,CopyOnWriteArrayList新建立了一個大小比原來小1的新陣列,然後利用System.arraycopy將原陣列index前後分兩次複製至新陣列。


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/28912557/viewspace-1133900/,如需轉載,請註明出處,否則將追究法律責任。

相關文章