自從JDK1.5引入引入concurrentHashmap,CopyOnWriteArraylist等併發集合後,java集合體係獲得了很大的完善,咱們有多了很多特殊情境的選擇。 java
咱們都知道,ArrayList存數數據的結構爲數組,獲取數據是根據數組下標,所以獲取數據速度很快,而插入(中間)數據,刪除數據卻須要copy數組,所以速度較慢,而相比之下, CopyOnWriteArraylist底層的存儲依然是數組,可是基本操做卻不大同樣。
數組
好處(使用場景):併發
Copy-On-Write簡稱COW,是一種用於程序設計中的優化策略。其基本思路是,從一開始你們都在共享同一個內容,當某我的想要修改這個內容的時候,纔會真正把內容Copy出去造成一個新的內容而後再改,這是一種延時懶惰策略。從JDK1.5開始Java併發包裏提供了兩個使用CopyOnWrite機制實現的併發容器,它們是CopyOnWriteArrayList和CopyOnWriteArraySet。CopyOnWrite容器很是有用,能夠在很是多的併發場景中使用到。
app
CopyOnWriteArrayList經過修改時拷貝原數組,而獲取數組時返回老數組(至關於快照),使得修改和查看(遍歷)的線程操做的是不一樣數組,達到避免併發修改的問題 性能
缺點(不宜使用):優化
由於CopyOnWrite的寫時複製機制,因此在進行寫操做的時候,內存裏會同時駐紮兩個對象的內存,舊的對象和新寫入的對象(注意:在複製的時候只是複製容器裏的引用,只是在寫的時候會建立新對象添加到新容器裏,而舊容器的對象還在使用,因此有兩份對象內存)。若是這些對象佔用的內存比較大,好比說200M左右,那麼再寫入100M數據進去,內存就會佔用300M,那麼這個時候頗有可能形成頻繁的Yong GC和Full GC。以前咱們系統中使用了一個服務因爲每晚使用CopyOnWrite機制更新大對象,形成了每晚15秒的Full GC,應用響應時間也隨之變長。 this
針對內存佔用問題,能夠經過壓縮容器中的元素的方法來減小大對象的內存消耗,好比,若是元素全是10進制的數字,能夠考慮把它壓縮成36進制或64進制。或者不使用CopyOnWrite容器,而使用其餘的併發容器,如ConcurrentHashMap。spa
CopyOnWrite容器只能保證數據的最終一致性,不能保證數據的實時一致性。因此若是你但願寫入的的數據,立刻能讀到,請不要使用CopyOnWrite容器。線程
每次寫都要複製的操做天然形成操做性能的降低。設計
代碼:
/** * 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; }