并發(fā)編程:并發(fā)容器,我們一起了解一下!
一、BlockingQueue
在所有的并發(fā)容器中,BlockingQueue是最常見的一種。BlockingQueue是一個帶阻塞功能的隊列,當(dāng)入隊列時,若隊列已滿,則阻塞調(diào)用者;當(dāng)出隊列時,若隊列為空,則阻塞調(diào)用者。
在Concurrent包中,BlockingQueue是一個接口,有許多個不同的實(shí)現(xiàn)類,如圖所示。
1、ArrayBlockingQueue是一個用數(shù)組實(shí)現(xiàn)的環(huán)形隊列,在構(gòu)造方法中,會要求傳入數(shù)組的容量。
2、LinkedBlockingQueue是一種基于單向鏈表的阻塞隊列。因?yàn)殛狀^和隊尾是2個指針分開操作的, 所以用了2把鎖+2個條件,同時有1個AtomicInteger的原子變量記錄count數(shù)。
3、PriorityBlockingQueue 隊列通常是先進(jìn)先出的,而PriorityQueue是按照元素的優(yōu)先級從小到大出隊列的。正因?yàn)槿绱耍?PriorityQueue中的2個元素之間需要可以比較大小,并實(shí)現(xiàn)Comparable接口。
4、DelayQueue即延遲隊列,也就是一個按延遲時間從小到大出隊的PriorityQueue。所謂延遲時間, 就是“未來將要執(zhí)行的時間”減去“當(dāng)前時間”。為此,放入DelayQueue中的元素,必須實(shí)現(xiàn)Delayed接 口。
5、SynchronousQueue是一種特殊的BlockingQueue,它本身沒有容量。先調(diào)put(...),線程會阻塞; 直到另外一個線程調(diào)用了take(),兩個線程才同時解鎖,反之亦然。對于多個線程而言,例如3個線程, 調(diào)用3次put(...),3個線程都會阻塞;直到另外的線程調(diào)用3次take(),6個線程才同時解鎖,反之亦然。
二、BlockingDeque
BlockingDeque定義了一個阻塞的雙端隊列接口,如下所示。
該接口繼承了BlockingQueue接口,同時增加了對應(yīng)的雙端隊列操作接口。該接口只有一個實(shí)現(xiàn), 就是LinkedBlockingDeque。
三、CopyOnWrite
CopyOnWrite指在“寫”的時候,不是直接“寫”源數(shù)據(jù),而是把數(shù)據(jù)拷貝一份進(jìn)行修改,再通過悲觀鎖或者樂觀鎖的方式寫回。
那為什么不直接修改,而是要拷貝一份修改呢? 這是為了在“讀”的時候不加鎖。
1、CopyOnWriteArrayList
和ArrayList一樣,CopyOnWriteArrayList的核心數(shù)據(jù)結(jié)構(gòu)也是一個數(shù)組。
2、CopyOnWriteArraySet
CopyOnWriteArraySet 就是用 Array 實(shí)現(xiàn)的一個 Set,保證所有元素都不重復(fù)。其內(nèi)部是封裝的一 個CopyOnWriteArrayList。