Java集合---CopyOnWriteArrayList(5)

用途與特色
可用於多讀取,寫入須要線程安全的狀況使用。算法

實現算法數組

該集合如其名字同樣,是先建立一個新的數組,而後將舊的數組copy到新數組中,再切換數組引用。而且該數組是在每次添加時都會執行以上流程,因此不建議在多寫入的場景使用。安全

該集合在多併發時使用ReentrantLock鎖來處理併發問題,比Vector中synchronized的效率會高一些,但在並法過程當中可能會出現髒讀問題,如兩個線程一個執行讀取數組數量,一個在作寫入操做,如在寫入操做以前,還沒作size++操做前,另一個線程讀取size值,此時還時未增長的數量,會產生髒讀。併發

添加app

CopyOnWriteArrayList

/**
     * 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版本源碼解讀

相關文章
相關標籤/搜索