摘要:前言今天我們一起學習下并發包里的工具類。的定義如下它也屬于集合框架的一部分,是的線程安全的變體,跟的不同在于針對數組的修改操作等是基于內部拷貝的一份數據而進行的。發生修改時候做,新老版本分離,保證讀的高性能,適用于以讀為主的情況。
前言
今天我們一起學習下java.util.concurrent并發包里的CopyOnWriteArrayList工具類。當有多個線程可能同時遍歷、修改某個公共數組時候,如果不希望因使用synchronize關鍵字鎖住整個數組而影響性能,可以考慮使用CopyOnWriteArrayList。
CopyOnWriteArrayList APICopyOnWriteArrayList的定義如下:
public class CopyOnWriteArrayListextends Object implements List , RandomAccess, Cloneable, Serializable
它也屬于Java集合框架的一部分,是[ArrayList]()的線程安全的變體,跟ArrayList的不同在于:CopyOnWriteArrayList針對數組的修改操作(add、set等)是基于內部拷貝的一份數據而進行的。換句話說,即使在一個線程進行遍歷操作時有其他線程可能進行插入或刪除操作,我們也可以“線程安全”得遍歷CopyOnWriteArrayList。
例子1:插入(刪除)數據的同時進行遍歷CopyOnWriteArrayList的實現原理是,在一個線程開始遍歷(創建Iterator對象)時,內部會創建一個“快照”數組,遍歷基于這個快照Iterator進行,在遍歷過程中這個快照數組不會改變,也就不會拋出ConcurrentModificationException。如果在遍歷的過程中有其他線程嘗試改變數組的內容,就會拷貝一份新的數據進行變更,而后面再來訪問這個數組的線程,看到的就是變更過的數組。
創建一個CopyOnWriteArrayList數組numbers;
CopyOnWriteArrayListnumbers = new CopyOnWriteArrayList<>(new Integer[]{1, 3, 5, 78});
?
創建一個遍歷器iterator;
Iteratoriterator = numbers.iterator();
?
給numbers中增加(或刪除、修改)一個元素;
numbers.add(100);
?
利用iterator遍歷數組的元素,發現遍歷的結果是Iterator對象創建之前的;
Listresult = new LinkedList<>(); iterator.forEachRemaining(result::add); assertThat(result).containsOnly(1, 3, 5, 78);
完整的例子如下:
package org.java.learn.concurrent.copyonwritearraylist; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import static org.assertj.core.api.Assertions.*; /** * 作用: * User: duqi * Date: 2017/11/9 * Time: 11:20 */ public class CopyOnWriteArrayListExample { public static void main(String[] args) { CopyOnWriteArrayList例子2:不支持一邊遍歷一邊刪除numbers = new CopyOnWriteArrayList<>(new Integer[]{1, 3, 5, 78}); Iterator iterator = numbers.iterator(); numbers.add(100); List result = new LinkedList<>(); iterator.forEachRemaining(result::add); assertThat(result).containsOnly(1, 3, 5, 78); Iterator iterator2 = numbers.iterator(); numbers.remove(3); List result2 = new LinkedList<>(); iterator2.forEachRemaining(result2::add); assertThat(result2).containsOnly(1, 3, 5, 78, 100); } }
由于CopyOnWriteArrayList的實現機制——>修改操作和讀操作拿到的Iterator對象指向的不是一個數組,因此不支持基于Iterator對象的方法結果的刪除:public void remove();,例子代碼如下:
package org.java.learn.concurrent.copyonwritearraylist; import java.util.Iterator; import java.util.concurrent.CopyOnWriteArrayList; /** * 作用: User: duqi Date: 2017/11/9 Time: 13:40 */ public class CopyOnWriteArrayListExample2 { public static void main(String[] args) { try { testExceptionThrow(); } catch (Exception e) { e.printStackTrace(); } } private static void testExceptionThrow() { CopyOnWriteArrayList結論numbers = new CopyOnWriteArrayList<>(new Integer[]{1, 3, 5, 78}); Iterator integerIterator = numbers.iterator(); while (integerIterator.hasNext()) { integerIterator.remove(); } } }
CopyOnWriteArrayList適合使用在讀操作遠遠大于寫操作的場景里,比如緩存。發生修改時候做copy,新老版本分離,保證讀的高性能,適用于以讀為主的情況。
參考資料Guide to CopyOnWriteArrayList
CopyOnWriteArrayList詳解
官方文檔:CopyOnWriteArrayList
本號專注于后端技術、JVM問題排查和優化、Java面試題、個人成長和自我管理等主題,為讀者提供一線開發者的工作和成長經驗,期待你能在這里有所收獲。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/75532.html
摘要:提供了線程安全的共享對象,在編寫多線程代碼時,可把不安全的整個變量封裝進,或者把該對象與線程相關的狀態使用保存并不能替代同步機制,兩者面向的問題領域不同。 ThreadLocal類 使用ThreadLocal類可以簡化多線程編程時的并發訪問,使用這個工具類可以很簡捷地隔離多線程程序的競爭資源。Java5之后,為ThreadLocal類增加了泛型支持,即ThreadLocal Threa...
摘要:同步容器及其注意事項中的容器主要可以分為四個大類,分別是和,但并不是所有的容器都是線程安全的。并發容器及其注意事項在版本之前所謂的線程安全的容器,主要指的就是同步容器,當然因為所有方法都用來保證互斥,串行度太高了,性能太差了。 Java 并發包有很大一部分內容都是關于并發容器的,因此學習和搞懂這部分的內容很有必要。 Java 1.5 之前提供的同步容器雖然也能保證線程安全,但是性能很差...
摘要:今天主要講解的是本文力求簡單講清每個知識點,希望大家看完能有所收獲一和回顧線程安全的和我們知道是用于替代的,是線程安全的容器。使用迭代器遍歷時不需要顯示加鎖,看看與方法的實現可能就有點眉目了。 前言 只有光頭才能變強 showImg(https://segmentfault.com/img/remote/1460000016931828?w=1120&h=640); 前一陣子寫過一篇C...
摘要:體現的就是適配器模式。數組對象集合世界中的機制機制集合世界中比較常見的錯誤檢測機制,防止在對集合進行遍歷過程當中,出現意料之外的修改,會通過異常暴力的反應出來。而在增強循環中,集合遍歷是通過進行的。 前言 學習情況記錄 時間:week 2 SMART子目標 :Java 容器 記錄在學習Java容器 知識點中,關于List的重點知識點。 知識點概覽: 容器中的設計模式 從Array...
摘要:并發數據結構存在的理由串行數據結構在并發環境下是不安全的,而直接使用鎖又會帶來性能的影響,所以專門設計了針對并發環境下的數據結構,其中使用了無鎖運算來保證性能。在高并發的情況下過多的鎖操作會拖累系統的性能。是由數組結構和數組結構組成。 【并發數據結構存在的理由 串行數據結構在并發環境下是不安全的,而直接使用鎖又會帶來性能的影響,所以jdk專門設計了針對并發環境下的數據結構,其中使用了無...
閱讀 3869·2021-10-08 10:05
閱讀 2950·2021-09-27 13:57
閱讀 2685·2019-08-29 11:32
閱讀 1010·2019-08-28 18:18
閱讀 1292·2019-08-28 18:05
閱讀 1989·2019-08-26 13:39
閱讀 868·2019-08-26 11:37
閱讀 2047·2019-08-26 10:37