CopyOnWriteArrayList 源碼---JDK1.8
阿新 • • 發佈:2017-12-05
element tar 進行 jdk1.8 bound object system 線程安全 寫時復制
CopyOnWriteArrayList:通過copy一份以前元素的快照,是一種讀寫分離的並發策略,我們也可以稱這種容器為"寫時復制器"。該集合適合讀多寫少的場景(讀沒有加鎖,其他更新操作均有加鎖)。
/** The lock protecting all mutators */ final transient ReentrantLock lock = new ReentrantLock(); /** The array, accessed only via getArray/setArray. */ //volatile修飾,如果數組發生改變其他線程可見 privatetransient volatile Object[] array;
元素添加,上鎖,線程安全的,每次只允許一個線程對該集合修改。
//添加元素到列表尾部 public boolean add(E e) { final ReentrantLock lock = this.lock; //上鎖 lock.lock(); try { //獲取數組的快照 Object[] elements = getArray(); //原數組長度 intlen = elements.length; //每次增加元素的時候,都會進行數組copy Object[] newElements = Arrays.copyOf(elements, len + 1); //將新元素保存到數組中 newElements[len] = e; //更新原數組 setArray(newElements); return true; } finally { lock.unlock(); } }
在指定位置上添加元素:
//在指定位置上添加元素,支持重復元素 public void add(int index, E element) { final ReentrantLock lock = this.lock; lock.lock(); 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; //如果為0,說明要添加的位置是尾部 if (numMoved == 0) //直接len+1,copy newElements = Arrays.copyOf(elements, len + 1); else { //創建一個新數組,長度len+1 newElements = new Object[len + 1]; //copy,0--->index System.arraycopy(elements, 0, newElements, 0, index); //copy,index+1--->end System.arraycopy(elements, index, newElements, index + 1, numMoved); } newElements[index] = element; setArray(newElements); } finally { lock.unlock(); } }
更新指定位置上的元素:
//添加元素到指定位置,如果指定位置存在相同元素,什麽也不做 public E set(int index, E element) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); E oldValue = get(elements, index); //要插入的元素和舊元素不一樣 if (oldValue != element) { int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len); //更新以前位置上的元素 newElements[index] = element; setArray(newElements); } else { // Not quite a no-op; ensures volatile write semantics setArray(elements); } return oldValue; } finally { lock.unlock(); } }
獲取指定位置上的元素:
//獲取指定位置上的元素 public E get(int index) { return get(getArray(), index); } //獲取指定位置元素 private E get(Object[] a, int index) { return (E) a[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; //為0,說明移除的是尾部元素 if (numMoved == 0) setArray(Arrays.copyOf(elements, len - 1)); //不為0,需要將將index前後2部分數組分別copy else { Object[] newElements = new Object[len - 1]; //copy 0--index System.arraycopy(elements, 0, newElements, 0, index); //copy index+1--->end System.arraycopy(elements, index + 1, newElements, index, numMoved); //更新數組 setArray(newElements); } return oldValue; } finally { lock.unlock(); } }
CopyOnWriteArrayList 源碼---JDK1.8