java集合之CopyOnWriteArrayList
CopyOnWriteArrayList
CopyOnWriteArrayList是juc中提供的併發安全的ArrayList,我們拆分一下類名"Copy""On""Write""ArrayList",從字面意思我們推斷出,這個是以在Write時進行Copy陣列元素的ArrayList;
它主要具有一下特性:
- 它是執行緒安全的;
- 允許元素為null;
- 支援隨機訪問、淺拷貝,可序列化;
- 迭代器使用快照方式,且在迭代期間陣列不會改變,故不會出現併發異常;
- 可變操作(set,add,remove,clear,replace,sort,sublist等等)的開銷很大,因為通常需要複製整個基礎陣列;
- 所有的get方法只是獲取陣列對應下標上的元素(無需加鎖控制)
CopyOnWriteArrayList使用了一種叫寫時複製的方法,當有新元素新增到CopyOnWriteArrayList時,先將原有陣列的元素拷貝到新陣列中,然後在新的陣列中做寫操作,寫完之後,再將原來的陣列引用(volatile修飾的陣列引用)指向新陣列;
CopyOnWriteArrayList提供了弱一致性的迭代器,保證在獲取迭代器後,其他執行緒對list的修改該不可見,迭代器遍歷時候的陣列是獲取迭代器時候的一個快照;
CopyOnWriteArrayList是使用空間換時間的方式進行工作,它主要適用於讀多些少,並且資料內容變化比較少的場景(最好初始化時就進行載入資料到CopyOnWriteArrayList中);
- add(E e):新增元素
public boolean add(E e) {
/**
* 增加元素 e 到陣列的末尾
* 操作步驟:
* 1. 獲取全域性的 reentrantLock
* 2. 將原來的 array1 copy 到一個 array.length + 1 的陣列 array2 裡面
* 3. 將 先新增的元素e新增到新陣列 array2 的最後一個空間裡面 (array2[array2.length - 1] = e)
* 4. 將 新陣列 array2 賦值給 CopyOnWriteArrayList 中的 array
*/
final ReentrantLock lock = this.lock;
lock.lock(); // 1. 獲取 全域性 lock
try{
Object[] elements = getArray(); // 2. 獲取原來的陣列
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1); // 3. 新建一個 array2 將原來的資料賦值到這個新建的陣列裡面
newElements[len] = e; // 4. 將 e 賦值給 array2的最後一個空間裡面
setArray(newElements); // 5. 將新陣列 array2 賦值給 CopyOnWriteArrayList 中的 array
return true;
}finally {
lock.unlock(); // 6. 釋放鎖
}
}
- add(int index, E element):新增元素到指定位置
public void add(int index, E element) {
/**
* 將元素 e 插入到陣列 指定的索引下標 index 下
* 操作步驟:
* 1. 獲取全域性的鎖
* 2. 獲取 CopyOnWriteArrayList 的 array, 及 array.length
* 3. 進行引數校驗 (index > len || index < 0) 則直接拋異常 -> 說明元素的插入只能在 0 - array.length 之間(包含兩個端點)
* 4. 獲取插入點 index 與 array.length 之間的步長, 進行分類討論
* 1) 插入的資料正好在 原array陣列的後一個節點 (numMoved = len), 則直接新建一個 array, 將原來的 array copy 過來
* 2) 插入的 index 滿足 0 <= index <= len - 1, 則新建一個陣列, 原來 o -> index(index不包含) 拷貝來, index後面的資料拷貝到新陣列的 index + 1 的空間
* 5. 將 e 設定到 新 array 的 index 位置
* 6. 將 新 array 設定到 CopyOnWriteArrayList 裡面
*/
final ReentrantLock lock = this.lock;
lock.lock(); // 1. 獲取全域性的鎖
try{
Object[] elements = getArray();
int len = elements.length;
if(index > len || index < 0){
throw new IndexOutOfBoundsException("Index: " + index + ", Size:" + len);
}
Object[] newElements;
int numMoved = len - index;
if(numMoved == 0){ // 走到這一步, 說明資料是插入到oldArray.length(這個值是指下標) 位置上的元素
newElements = Arrays.copyOf(elements, len + 1); // 直接拷貝原陣列到一個新的 array 陣列中, 這個陣列的長度是 len + 1
}else{
newElements = new Object[len + 1];
System.arraycopy(elements, 0, newElements, 0, index); // 將原陣列 index 前的陣列都拷貝到新的陣列裡面
System.arraycopy(elements, index, newElements, index + 1, numMoved); // 將原陣列 index 以後的元素都 copy到新的陣列裡面(包括index位置的元素)
}
newElements[index] = element; // 將 index 賦值 element
setArray(newElements); // 將 新的 array set到 CopyOnWriteArrayList 上
}finally {
lock.unlock();
}
}
- remove(int index):刪除指定位置元素
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){ // 說明刪除的元素的位置在 len - 1 上, 直接拷貝原陣列的前 len - 1 個元素
setArray(Arrays.copyOf(elements, len - 1));
}else{
Object[] newElements = new Object[len - 1];
System.arraycopy(elements, 0, newElements, 0, index); // 拷貝原陣列 0 - index之間的元素 (index 不拷貝)
System.arraycopy(elements, index + 1, newElements, index, numMoved); // 拷貝原陣列 index+1 到末尾之間的元素 (index+1也進行拷貝)
setArray(newElements);
}
}finally {
lock.unlock();
}
return null;
相關文章
- 死磕 java集合之CopyOnWriteArrayList原始碼分析Java原始碼
- Java集合乾貨——CopyOnWriteArrayList原始碼分析Java原始碼
- java併發之CopyOnWriteArrayListJava
- Java併發包之 CopyOnWriteArrayListJava
- 圖解集合3:CopyOnWriteArrayList圖解
- java併發資料結構之CopyOnWriteArrayListJava資料結構
- Java併發-CopyOnWriteArrayListJava
- Java JUC CopyOnWriteArrayList 解析Java
- java中CopyOnWriteArrayList詳解Java
- Java 集合之ArrayListJava
- Java集合之HashMapJavaHashMap
- Java集合之ArrayListJava
- Java之Properties集合Java
- 併發容器之CopyOnWriteArrayList
- Java 集合之LinkedListJava
- Java集合之LinkedHashMapJavaHashMap
- Java集合系列之---HashMapJavaHashMap
- Java集合系列之HashMapJavaHashMap
- jdk原始碼分析之CopyOnWriteArrayListJDK原始碼
- Java高階特性之集合Java
- java之陣列與集合Java陣列
- Java集合系列之LinkedHashMapJavaHashMap
- CopyOnWriteArrayList
- Java集合框架之 Java HashMap 原始碼解析Java框架HashMap原始碼
- 面試必備 之 Java 集合框架面試Java框架
- Java 集合(2)之 Iterator 迭代器Java
- Java集合(5)之 List 總結Java
- Java集合之Hashtable原始碼解析Java原始碼
- Java集合之ArrayList原始碼解析Java原始碼
- Java基礎之淺談集合Java
- Java集合之HashMap原始碼解析JavaHashMap原始碼
- 面試必問之 CopyOnWriteArrayList,你瞭解多少?面試
- Java集合(6)之 HashMap 原始碼解析JavaHashMap原始碼
- Java 集合(1)之 總體架構Java架構
- 死磕 java集合之終結篇Java
- 再說Java集合,subList之於ArrayListJava
- Java之常見異常 整理集合Java
- 帶你走進Java集合之ArrayListJava