Java集合框架02——線程安全的集合詳解

一、早期線程安全的集合

我們先從早期的線程安全的集合說起,它們是Vector和HashTable

1. Vector

     Vector和ArrayList類似,是長度可變的數組,與ArrayList不同的是,Vector是線程安全的,它給幾乎所有的public方法都加上了synchronized關鍵字。由於加鎖導致性能降低,在不需要併發訪問同一對象時,這種強制性的同步機制就顯得多餘,所以現在Vector已被棄用

2. HashTable

      HashTable和HashMap類似,不同點是HashTable是線程安全的,它給幾乎所有public方法都加上了synchronized關鍵字,還有一個不同點是HashTable的K,V都不能是null,但HashMap可以,它現在也因爲性能原因被棄用了

二、Collections包裝方法

   Vector和HashTable被棄用後,它們被ArrayList和HashMap代替,但它們不是線程安全的,所以Collections工具類中提供了相應的包裝方法把它們包裝成線程安全的集合

List<E> synArrayList = Collections.synchronizedList(new ArrayList<E>());

Set<E> synHashSet = Collections.synchronizedSet(new HashSet<E>());

Map<K,V> synHashMap = Collections.synchronizedMap(new HashMap<K,V>());

...

    Collections針對每種集合都聲明瞭一個線程安全的包裝類,在原集合的基礎上添加了鎖對象,集合中的每個方法都通過這個鎖對象實現同步

三、java.util.concurrent包中的集合

1.  ConcurrentHashMap

     ConcurrentHashMap和HashTable都是線程安全的集合,它們的不同主要是加鎖粒度上的不同。HashTable的加鎖方法是給每個方法加上synchronized關鍵字,這樣鎖住的是整個Table對象。而ConcurrentHashMap是更細粒度的加鎖 
在JDK1.8之前,ConcurrentHashMap加的是分段鎖,也就是Segment鎖,每個Segment含有整個table的一部分,這樣不同分段之間的併發操作就互不影響 
JDK1.8對此做了進一步的改進,它取消了Segment字段,直接在table元素上加鎖,實現對每一行進行加鎖,進一步減小了併發衝突的概率

2. CopyOnWriteArrayList和CopyOnWriteArraySet

    它們是加了寫鎖的ArrayList和ArraySet,鎖住的是整個對象,但讀操作可以併發執行

3.  除此之外還有ConcurrentSkipListMap、ConcurrentSkipListSet、ConcurrentLinkedQueue、ConcurrentLinkedDeque等,至於爲什麼沒有ConcurrentArrayList,原因是無法設計一個通用的而且可以規避ArrayList的併發瓶頸的線程安全的集合類,只能鎖住整個list,這用Collections裏的包裝類就能辦到

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章