【源碼分析篇】CopyOnWriteArrayList
add()
public boolean add(E e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); } }
- 先去獲取鎖,若沒(méi)有獲取鎖,則阻塞
- 將原來(lái)的數(shù)組拷貝一份,然后在新數(shù)組上進(jìn)行添加操作
- 將新數(shù)組賦值給舊數(shù)組
get()
public E get(int index) { return get(getArray(), index); } private E get(Object[] a, int index) { return (E) a[index]; }
get()方法直接在原數(shù)組上面進(jìn)行操作,所以CopyOnWriteArrayList不會(huì)保證數(shù)組的實(shí)時(shí)性,但可以保證數(shù)據(jù)的最終一致性,它適用于寫多讀少的場(chǎng)景,如果對(duì)數(shù)據(jù)實(shí)時(shí)性要求較高的話,不推薦適用CopyOnWriteArrayList。
remove()
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) 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); } return oldValue; } finally { lock.unlock(); } }
- 和add()方法一樣,remove方法也是先獲取鎖,沒(méi)有則阻塞
- 獲取到鎖了則判斷當(dāng)前元素下標(biāo)是否為最后一個(gè)元素,若為最后一個(gè)元素,則只需要進(jìn)行一次數(shù)組拷貝即可,若不是,則需要進(jìn)行兩次數(shù)組拷貝,分別是該元素前半部分和該元素后半部分。
- 最后再給源數(shù)組賦值。
鄙人新開(kāi)設(shè)的模塊,之后會(huì)將微信公眾號(hào)【An前碼后】中的文章陸續(xù)搬遷到??途W(wǎng),若想閱讀更多的源碼解析,請(qǐng)關(guān)注微信公眾號(hào)【An前碼后】