併發容器的簡單介紹
JDK5中添加了新的concurrent包,相對同步容器而言,併發容器經過一些機制改進了併發性能。由於同步容器將全部對容器狀態的訪問都串行化了,這樣保證了線程的安全性,因此這種方法的代價就是嚴重下降了併發性,當多個線程競爭容器時,吞吐量嚴重下降。所以Java5.0開始針對多線程併發訪問設計,提供了併發性能較好的併發容器,引入了java.util.concurrent包。與Vector和Hashtable、Collections.synchronizedXxx()同步容器等相比,util.concurrent中引入的併發容器主要解決了兩個問題:java
- 1)根據具體場景進行設計,儘可能避免synchronized,提供併發性。
- 2)定義了一些併發安全的複合操做,而且保證併發環境下的迭代操做不會出錯。
util.concurrent中容器在迭代時,能夠不封裝在synchronized中,能夠保證不拋異常,可是未必每次看到的都是"最新的、當前的"數據。算法
併發容器類簡單介紹
ConcurrentHashMap
- 對應的非併發容器:HashMap
- 目標:代替Hashtable、synchronizedMap,支持複合操做
- 原理:JDK6中採用一種更加細粒度的加鎖機制Segment「分段鎖」,JDK8中採用CAS無鎖算法。
CopyOnWriteArrayList
- 對應的非併發容器:ArrayList
- 目標:代替Vector、synchronizedList
- 原理:利用高併發每每是讀多寫少的特性,對讀操做不加鎖,對寫操做,先複製一份新的集合,在新的集合上面修改,而後將新集合賦值給舊的引用,並經過volatile 保證其可見性,固然寫操做的鎖是必不可少的了。
CopyOnWriteArraySet
- 對應的費併發容器:HashSet
- 目標:代替synchronizedSet
- 原理:基於CopyOnWriteArrayList實現,其惟一的不一樣是在add時調用的是CopyOnWriteArrayList的addIfAbsent方法,其遍歷當前Object數組,如Object數組中已有了當前元素,則直接返回,若是沒有則放入Object數組的尾部,並返回。
ConcurrentSkipListMap
- 對應的非併發容器:TreeMap
- 目標:代替synchronizedSortedMap(TreeMap)
- 原理:Skip list(跳錶)是一種能夠代替平衡樹的數據結構,默認是按照Key值升序的。Skip list讓已排序的數據分佈在多層鏈表中,以0-1隨機數決定一個數據的向上攀升與否,經過」空間來換取時間」的一個算法。ConcurrentSkipListMap提供了一種線程安全的併發訪問的排序映射表。內部是SkipList(跳錶)結構實現,在理論上可以在O(log(n))時間內完成查找、插入、刪除操做。
ConcurrentSkipListSet
- 對應的非併發容器:TreeSet
- 目標:代替synchronizedSortedSet
- 原理:內部基於ConcurrentSkipListMap實現
ConcurrentLinkedQueue
- 不會阻塞的隊列
- 對應的非併發容器:Queue
- 原理:基於鏈表實現的FIFO隊列(LinkedList的併發版本)
LinkedBlockingQueue、ArrayBlockingQueue、PriorityBlockingQueue
- 對應的非併發容器:BlockingQueue
- 特色:拓展了Queue,增長了可阻塞的插入和獲取等操做
- 原理:經過ReentrantLock實現線程安全,經過Condition實現阻塞和喚醒
- 實現類:
- LinkedBlockingQueue:基於鏈表實現的可阻塞的FIFO隊列
- ArrayBlockingQueue:基於數組實現的可阻塞的FIFO隊列
- PriorityBlockingQueue:按優先級排序的隊列