在Java類庫中出現的第一個關聯的集合類是 Hashtable
。 Hashtable
提供了一種易於使用的、線程安全的、關聯的map功能。然而,線程安全性付出代價是――Hashtable
的所有方法都是同步的。Hashtable
的後繼者HashMap
是作爲JDK1.2中的集合框架的一部分出現的,它通過提供一個不同步的基類和一個同步的包裝器Collections.synchronizedMap
,解決了線程安全性問題。通過將基本的功能從線程安全性中分離開來,Collections.synchronizedMap
允許需要同步的用戶可以擁有同步,而不需要同步的用戶則不必爲同步付出代價。
同步的集合包裝器 synchronizedMap
和 synchronizedList
,有時也被稱作 有條件地線程安全――所有單個的操作都是線程安全的,但是多個操作組成的操作序列卻可能導致數據爭用,因爲在操作序列中控制流取決於前面操作的結果。例如對於這樣的功能put-if-absent語句塊――如果一個條目不在Map
中,那麼添加這個條目。該功能通過containsKey()
方法和 put()
方法組合起來。要保證原子性操作,就需要對該語句塊加上同步鎖。
Queue接口
java.util 包爲集合提供了一個新的基本接口:java.util.Queue,是一個先入先出(FIFO)的數據結構。
PriorityQueue類
BlockingQueue接口
阻塞隊列,它實質上就是一種帶有一點扭曲的 FIFO 數據結構。它提供了可阻塞的put和take方法。如果Queue已經滿了,put方法會被阻塞直到有空間可用;如果Queue是空的,那麼take方法會被阻塞,直到有元素可用。Queue的長度可用有限,也可以無限;無限的Queue永遠不會充滿,所以它的put方法永遠不會被阻塞。阻塞隊列支持生產者-消費者設計模式。BlockingQueue可以使用任意數量的生產者和消費者,從而簡化了生產者-消費者設計的實現。
BlockingQueue接口的幾個主要的實現類:
ArrayBlockingQueue
:一個由數組支持的有界隊列。 LinkedBlockingQueue
:一個由鏈接節點支持的可選有界隊列。 PriorityBlockingQueue
:一個由優先級堆支持的無界優先級隊列。 DelayQueue
:一個由優先級堆支持的、基於時間的調度隊列。 SynchronousQueue
:一個利用 BlockingQueue
接口的簡單聚集(rendezvous)機制。
PriorityBlockingQueue
是具有無界限容量的隊列,它利用所包含元素的 Comparable
排序順序來以邏輯順序維護元素。可以將它看作TreeSet
的可能替代物。對於沒有天然順序的元素,可以爲構造函數提供一個Comparator
。不過對PriorityBlockingQueue,有一個要特別注意的地方:
從
iterator()
返回的 Iterator
實例,元素是不具有優先級順序的。如果必須以優先級順序遍歷所有元素,那麼讓它們都通過toArray()
方法並自己對它們排序,像Arrays.sort(pq.toArray())
。
SynChronousQueue,它根本上不是一個真正的隊列,因爲它不會爲隊列元素維護任何存儲空間。不過,它維護一個排隊的線程清單,這些線程等待把元素加入隊列或移出隊列。它非常直接的移交工作,減少了生產者和消費者之間移動數據的延遲時間。直接移交同樣會給生產者帶來更多關於任務狀態的反饋信息:當移交被接受,它就知道消費者已經得到了任務。 因爲SynchronousQueue沒有存儲的能力,所以除非另一個線程已經準備好參與移交工作,否則put和take會一直阻塞。比較適合於消費者充足的情況。
CopyOnWriteArrayList 和 CopyOnWriteArraySet
,最適合於讀操作通常大大超過寫操作的情況。