CopyOnWriteArraylist解析

    自從JDK1.5引入引入concurrentHashmap,CopyOnWriteArraylist等併發集合後,java集合體係獲得了很大的完善,咱們有多了很多特殊情境的選擇。     java

    咱們都知道,ArrayList存數數據的結構爲數組,獲取數據是根據數組下標,所以獲取數據速度很快,而插入(中間)數據,刪除數據卻須要copy數組,所以速度較慢,而相比之下, CopyOnWriteArraylist底層的存儲依然是數組,可是基本操做卻不大同樣。
數組


好處(使用場景):併發

 Copy-On-Write簡稱COW,是一種用於程序設計中的優化策略。其基本思路是,從一開始你們都在共享同一個內容,當某我的想要修改這個內容的時候,纔會真正把內容Copy出去造成一個新的內容而後再改,這是一種延時懶惰策略。從JDK1.5開始Java併發包裏提供了兩個使用CopyOnWrite機制實現的併發容器,它們是CopyOnWriteArrayList和CopyOnWriteArraySet。CopyOnWrite容器很是有用,能夠在很是多的併發場景中使用到。
app

CopyOnWriteArrayList經過修改時拷貝原數組,而獲取數組時返回老數組(至關於快照),使得修改和查看(遍歷)的線程操做的是不一樣數組,達到避免併發修改的問題 性能

 

缺點(不宜使用):優化

     1.內存佔用問題

     由於CopyOnWrite的寫時複製機制,因此在進行寫操做的時候,內存裏會同時駐紮兩個對象的內存,舊的對象和新寫入的對象(注意:在複製的時候只是複製容器裏的引用,只是在寫的時候會建立新對象添加到新容器裏,而舊容器的對象還在使用,因此有兩份對象內存)。若是這些對象佔用的內存比較大,好比說200M左右,那麼再寫入100M數據進去,內存就會佔用300M,那麼這個時候頗有可能形成頻繁的Yong GC和Full GC。以前咱們系統中使用了一個服務因爲每晚使用CopyOnWrite機制更新大對象,形成了每晚15秒的Full GC,應用響應時間也隨之變長。 this

  針對內存佔用問題,能夠經過壓縮容器中的元素的方法來減小大對象的內存消耗,好比,若是元素全是10進制的數字,能夠考慮把它壓縮成36進制或64進制。或者不使用CopyOnWrite容器,而使用其餘的併發容器,如ConcurrentHashMapspa

 2.數據一致性問題

CopyOnWrite容器只能保證數據的最終一致性,不能保證數據的實時一致性。因此若是你但願寫入的的數據,立刻能讀到,請不要使用CopyOnWrite容器。線程

        3.性能。

    每次寫都要複製的操做天然形成操做性能的降低。設計

代碼:

 添加

 

/**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (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();
        }
    }

 

經過Arrays的copyOf方式複製數組,同時,寫的操做是須要併發控制的,採用了顯示鎖

寫的操做直接對新的數組執行


 

獲取數組

  final Object[] getArray() {
        return array;
    }

 


 

相關文章
相關標籤/搜索