併發容器有:
a. Java5.0中增加了ConcurrentHashMap(對應同步容器Hashtable)、CopyOnWriteArrayList(對應同步容器Vector)、CopyOnWriteArraySet(對應同步Set);
b. Java6.0中增加了ConcurrentSkipListMap(對應同步容器的Collections.synchronizedMap(new TreeMap()))、ConcurrentSkipListSet(對應同步容器的Collections.synchronizedSet(new TreeSet()))
與同步容器相比,併發容器有以下優勢:
a. 提高了性能:Java5.0提供了多種併發容器類來改進同步容器的性能;
b. 增加了併發性:併發容器是針對多個線程併發訪問設計的;
c. 將一些常見的併發操作實現爲原子操作:在新的ConcurrentMap接口中對一些常見覆合操作例如“若沒有則添加”、“若相等則移除”和“若相等則替換”等,都已經實現爲原子操作。
1. ConcurrentHashMap簡介
在Java6中,引入了ConcurrentSkipListMap和ConcurrentSkipListSet,分別作爲同步的SortedMap和SortedSet的併發替代品(例如用synchrozideMap包裝的TreeMap或TreeSet)。
與HashMap一樣,ConcurrentHashMap也是一個基於散列的Map,但它使用了一種完全不同的加鎖策略來提供更高的併發性和伸縮性。Hashtable與Collections.synchronizedMap(new HashMap())同步機制是把整個表都鎖住以提供獨佔訪問,即在每個公有方法上都添加一個synchronized關鍵字,使得在同一時刻,只能有一個線程在訪問這個表。而ConcurrentHashMap則使用粒度更細的分段鎖來實現更大程度的共享。使用分段鎖的好處是:
a. 任意數量的讀線程可以併發地訪問Map;
b. 執行讀操作地線程和執行寫操作地線程可以併發地訪問Map;
c. 一定數量地寫線程可以併發地修改Map;
ConcurrentHashMap帶來地結果是,在併發訪問環境下將實現更高的吞吐量,而在單線程環境中只損失非常小的性能。只有當應用程序需要加鎖Map以進行獨佔訪問時,才應該放棄使用ConcurrentHashMap。
2. CopyOnWriteArrayList
CopyOnWrite的字面意思是寫時複製,也是一種讀寫分離的思想,讀和寫操作的是不同的容器。CopyOnWrite容器可以進行併發的讀,而不需要加鎖;當我們往容器中添加元素的時候,不直接往當前容器添加,而是先將當前容器複製出一個新的容器,然後往新的容器裏添加元素,添加完元素之後,再將原容器的引用指向新的容器。注意:在讀的時候不需要加鎖,但在添加的時候,需要加鎖,否則多個線程在添加元素的時候會複製N個副本出來。
CopyOnWrite容器的應用場景是:讀多寫少;
CopyOnWrite容器的缺點:
a. 數據一致性問題:該類容器只能保證數據的最終一致性,不能保證數據的實時一致性。如果希望寫入的數據,馬上能讀到,使用CopyOnWrite容器是不合適的;
b. 內存佔用問題:CopyOnWrite容器在執行寫操作的時候,內存裏會同時存在兩個對象的內存,舊的對象和新複製的副本對象。如果這些對象佔用的內存比較大,那麼這個時候很有可能造成頻繁的Yong GC和Full GC。