用途與特色
可用於多讀取,寫入須要線程安全的狀況使用。算法
實現算法數組
該集合如其名字同樣,是先建立一個新的數組,而後將舊的數組copy到新數組中,再切換數組引用。而且該數組是在每次添加時都會執行以上流程,因此不建議在多寫入的場景使用。安全
該集合在多併發時使用ReentrantLock鎖來處理併發問題,比Vector中synchronized的效率會高一些,但在並法過程當中可能會出現髒讀問題,如兩個線程一個執行讀取數組數量,一個在作寫入操做,如在寫入操做以前,還沒作size++操做前,另一個線程讀取size值,此時還時未增長的數量,會產生髒讀。併發
添加app
/** * Appends the specified element to the end of this list. * * @param e element to be appended to this list * @return {@code true} (as specified by {@link Collection#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(); } }
刪除this
這裏說明一下,以前的幾個集合在刪除操做時都是不會對object[]數組進行操做,但這個集合會從新生成-1的新數組。因此能夠說該集合的數組長度與集合的實際數據佔用長度是相同的。線程
/** * Removes the element at the specified position in this list. * Shifts any subsequent elements to the left (subtracts one from their * indices). Returns the element that was removed from the list. * * @throws IndexOutOfBoundsException {@inheritDoc} */ 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(); } }
擴容機制code
擴容時機:在增長數據時,沒增長一個擴容一個blog
是否線程安全,爲何?ci
線程安全,在源碼中對數據操做使用ReentrantLock方法,保證了併發鎖。
具體ReentrantLock的使用詳解與synchronized有何區別,會在以後詳細查看併發時作補充。
根據jdk1.8版本源碼解讀