1. 程式人生 > >[Java 並發編程實戰] 集合框架之 同步容器類 & 並發容器類

[Java 並發編程實戰] 集合框架之 同步容器類 & 並發容器類

java 同步容器 並發編程 java集合框架 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接口,這是一個用於遍歷集合中元素的接口,主要包含以下三種方法:

  1. hasNext()是否還有下一個元素。

  2. next()返回下一個元素。

  3. remove()刪除當前元素。

對於 Java 集合框架,這裏不再做過多的說明,如果要完全剖析,那估計得再開一個專欄來講。下面對具體容器類分類,我們直接來看他們分別屬於哪些類型。

非同步集合

非同步集合,在並發訪問的時候,是非線程安全的;但是由於它們沒有同步策略(加鎖機制),它們的效率更高。常用的非同步集合它們包括下面幾個:

  • ArrayList

  • HashSet

  • HashMap

  • LinkedList

  • TreeSet

  • TreeMap

  • PriorityQueue

同步集合

對每個方法都進行同步加鎖,保證線程安全。

  • HashTable

  • Vector

  • Stack

  • 同步包裝器 : [ Collections.synchronizedMap(), Collections.synchronizedList() ]

Java 集合類中非線程安全的集合可以用同步包裝器使集合變成線程安全,其實實現原理就是相當於對每個方法加多一層同步鎖而已,比如:

  1. HashMap --> Collections.synchronizedMap(new HashMap())

  2. 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 並發編程實戰] 集合框架之 同步容器類 & 並發容器類