CopyOnWriteArrayList
線程安全版本ArrayList
-
新增元素
public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock();//進(jìn)行加鎖 try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1);//元素組進(jìn)行拷貝 newElements[len] = e;//將新元素加入到新數(shù)組中 setArray(newElements);//新數(shù)組重新賦值予原數(shù)組 return true; } finally { lock.unlock();//釋放鎖 } }- 每新加一個元素都會發(fā)生一次全數(shù)組拷貝
- 通過add(index,element)增加元素類似
- 類似于ArrayList通過addAll進(jìn)行批量的增加效率要高于單個加入
-
元素的刪除
public E remove(int index) { final ReentrantLock lock = this.lock; lock.lock();//加鎖 try { Object[] elements = getArray(); int len = elements.length; E oldValue = get(elements, index); int numMoved = len - index - 1; if (numMoved == 0)//當(dāng)移除最后一個元素時 setArray(Arrays.copyOf(elements, len - 1)); else { Object[] newElements = new Object[len - 1]; System.arraycopy(elements, 0, newElements, 0, index);//分段拷貝 System.arraycopy(elements, index + 1, newElements, index, numMoved); setArray(newElements);//元數(shù)據(jù)覆蓋 } return oldValue; } finally { lock.unlock(); } }- 發(fā)生一次數(shù)組對象拷貝
- 直接移除元素時,先找到其索引,然后通過以上方法進(jìn)行移除
- 同樣批量刪除的效率高于單個刪除
-
內(nèi)部類
- COWIterator
- next 向后訪問
- previous 向前訪問
- nextIndex 查看下一個索引值
- previousIndex 前一個索引值
- 不支持操作:remove,set,add
- 取值過程不進(jìn)行mod的檢查
- Spliterators.spliterator
- COWSubList
- COWIterator
-
特點
- 變更操作基本是先拷貝出一個副本,操作副本完成后,用副本更新原數(shù)據(jù)
SynchronizedList
線程安全List
-
在get/set/add/remove/indexOf/sort 內(nèi)部對象進(jìn)行加鎖處理
public E get(int index) { synchronized (mutex) {return list.get(index);} } 加鎖粒度比較大
兩者對比
- CopyOnWriteArrayList在數(shù)據(jù)讀上占據(jù)優(yōu)勢
- CopyOnWriteArrayList需要更大的內(nèi)存空間
- SynchronizedList使用迭代器需要自己進(jìn)行線程的同步