[Java 並發編程實戰] 集合框架之 同步容器類 & 並發容器類
吾生也有涯,而知也無涯。———《莊子》
通過上一篇文章,我們已經知道設計一個線程安全類的原則和步驟,以及在設計過程中我們應當註意的細節。實際上,Java 的集合庫包含了線程安全集合和非線程安全集合,可以說 Java 的線程安全集合庫就是按照前一篇說到的實例封閉、安全性的委托、組合這幾個方式來實現的。
這篇主要簡單介紹 Java 集合庫包含哪些常用的容器類,它們可以簡單區分為:
非同步集合
同步集合
並發集合
那麽,它們分別包括哪些具體的集合類,它們有什麽主要的區別,以及它們的框架是怎樣的?
這就是今天要講的內容,讀完這篇文章你應該要知道常用的集合庫有哪些具體容器類,多線程的情況下應該用哪種集合以及它們的主要區別。
Java 集合框架
Java 集合工具包在 Java.util 包下,它包含了常用的數據結構,比如數組、鏈表、棧、隊列、集合、哈希表等等。
這裏先放一張 Java 集合類的框架圖:
Java 集合框架
Collection 接口是集合類的根接口,Java 中沒有提供這個接口的直接的實現類。但是讓其被繼承產生了兩個接口,就是 Set 和 List。Set中不能包含重復的元素。List是一個有序的集合,可以包含重復的元素,提供了按索引訪問的方式。
Map 是 Java.util 包中的另一個接口,它和 Collection 接口沒有關系,是相互獨立的,但是都屬於集合類的一部分。Map 包含了 key-value 對。Map 不能包含重復的 key,但是可以包含相同的 value。
其中還有一個 Iterator 接口,Collection 繼承了它,也就是說所有的集合類,都實現了Iterator接口,這是一個用於遍歷集合中元素的接口,主要包含以下三種方法:
hasNext()是否還有下一個元素。
next()返回下一個元素。
remove()刪除當前元素。
對於 Java 集合框架,這裏不再做過多的說明,如果要完全剖析,那估計得再開一個專欄來講。下面對具體容器類分類,我們直接來看他們分別屬於哪些類型。
非同步集合
非同步集合,在並發訪問的時候,是非線程安全的;但是由於它們沒有同步策略(加鎖機制),它們的效率更高。常用的非同步集合它們包括下面幾個:
ArrayList
HashSet
HashMap
LinkedList
TreeSet
TreeMap
PriorityQueue
同步集合
對每個方法都進行同步加鎖,保證線程安全。
HashTable
Vector
Stack
同步包裝器 : [ Collections.synchronizedMap(), Collections.synchronizedList() ]
Java 集合類中非線程安全的集合可以用同步包裝器使集合變成線程安全,其實實現原理就是相當於對每個方法加多一層同步鎖而已,比如:
HashMap --> Collections.synchronizedMap(new HashMap())
ArrayList --> Collections.synchronizedList(new ArrayList<>())
並發集合
java.util.concurrent包下,並發容器類如下::
ConcurrentHashMap
ConcurrentSkipListMap
ConcurrentSkipListSet
CopyOnWriteArrayList
CopyOnWriteArraySet
ArrayBlockingQueue
LinkedBlockingQueue
PriorityBlockingQueue
LinkedBlockingDeque
ConcurrentLinkedQueue
同步集合類和並發集合類的區別
不管是同步集合還是並發集合他們都支持線程安全,他們之間主要的區別體現在性能和可擴展性,還有他們如何實現的線程安全。
同步集合類,Hashtable 和 Vector 還有同步集合包裝類,Collections.synchronizedMap()和Collections.synchronizedList(),相比並發的實現(比如:ConcurrentHashMap, CopyOnWriteArrayList, CopyOnWriteHashSet)會慢得多。
造成如此慢的主要原因是鎖, 同步集合會把整個Map或List鎖起來,每個操作都是串行的操作,同一時刻只有一個線程能操作。而並發集合不會,並發集合實現線程安全是通過使用先進的和成熟的技術把鎖剝離。
比如ConcurrentHashMap 會把整個Map 劃分成幾個片段,只對相關的幾個片段上鎖,同時允許多線程訪問其他未上鎖的片段。
CopyOnWriteArrayList 允許多個線程以非同步的方式讀,當有線程寫的時候它會將整個List復制一個副本給它。如果在讀多寫少這種對並發集合有利的條件下使用並發集合,這會比使用同步集合更具有可伸縮性。
本文完結,如果文章有誤,請批評指正;如果對你有幫助,可以關註我,謝謝!
[Java 並發編程實戰] 集合框架之 同步容器類 & 並發容器類