1. 程式人生 > >在面試中結構化的和麵試官聊聊執行緒安全的集合

在面試中結構化的和麵試官聊聊執行緒安全的集合

此案例發生在朋友的一次現場面試中,下面就以面試對話的形式展示出線上程安全的集合這個大的知識點下,面試官一般怎麼問。

最後再深入到執行緒安全的集合

(一)
問:看到你簡歷裡面寫到了,閱讀過部分集合的原始碼,那你知道哪些類是執行緒安全的?

答:Vector是ArrayList的執行緒安全版本,效能比ArrayList要低,現在已很少使用。Hashtable是執行緒安全的,現在也很少使用。在jdk1.8之後使用concurrentHashMap這個執行緒安全的集合比較多。

【期待問一下concurrentHashMap和hashTable的區別,就可以大展拳腳】

(二)
問:除此之外有沒有使用過其他執行緒安全的集合?

答:聽過synchronizedMap(Map<K, V> m): 返回指定Map物件對應的執行緒安全的Map物件。synchronizedSet(Set s): 返回指定Set物件對應的執行緒安全的Set物件。

【以為到此為止,問問原始碼什麼的】

(三)
問:恩,還不錯,那你是怎麼知道這些集合的,有沒有使用過?

答:。。。。布拉阿布拉。。。

【隨便扯就行,儘量變現自己好學,有好奇心】

最後面試官說學習有一個結構會更好,開始不懂原因,後面看來這個知識點,才知道當時的意思。

下面就結構化的看看執行緒安全的集合

1、以synchronized開頭命名的集合

看當多個併發向集合中存、取元素時,就可能會破壞這些集合的資料完整性。
如果程式中有多個執行緒可能訪問以上這些集合,就可以使用Collections提供的類方法把這些集合包裝成執行緒安全的集合。Collections提供瞭如下幾個靜態方法。

synchronizedCollection(Collection c): 返回指定collection 對應的執行緒安全的collection。

synchronizedList(List list): 返回指定List物件對應的執行緒安全的List 物件。

synchronizedMap(Map<K, V> m): 返回指定Map物件對應的執行緒安全的Map物件。

synchronizedSet(Set s): 返回指定Set物件對應的執行緒安全的Set物件。

synchronizedSortedMap(SortedMap<K, V> m): 返回指定SortedMap物件對應的執行緒安全的SortedMap物件

synchronizedSortedSet(SortedSet s): 返回指定SortedSet物件對應的執行緒安全的SortedSet物件。

大家都知道synchronized是同步鎖,前面有這個單詞的集合不用說,內部的資源和synchronized有聯絡,是安全的。

可以看到,在大家平常使用到的 List, Map, Set, Collection 給前面加上synchronized關鍵字就可以構成執行緒安全的集合。

例如需要在多執行緒裡使用執行緒安全的HashMap物件(如果需要把某個集合包裝成執行緒安全的集合,則應該在建立之後立即包裝,如下程式所示),則可以採用如下程式碼:

 // 使用Collections 的 synchronizedMap 方法將一個普通的HashMap包裝成執行緒安全的類
 HashMap m = Collections.synchronizedMap(new HashMap());

2、以Concurrent 開頭命名的集合

從Java 5 開始,在java.util.concurrent 包下提供了大量支援高效併發訪問的集合介面和實現類,如下圖所示:

在這裡插入圖片描述

看上圖中左邊部分

以Concurrent 開頭的集合類代表了支援併發訪問的集合,它們可以支援多個執行緒併發寫入訪問,這些寫入執行緒的所有操作都是執行緒安全的,但讀取操作不必鎖定。

以Concurrent 開頭的集合類採用了更復雜的演算法來保證永遠不會鎖住整個集合,因此在併發寫入時有較好的效能。

以Concurrent 開頭的集合類,
ConcurrentHashMap
還有不太常用的:
ConcurrentSkipListMap
ConcurrentSkipListSet
ConcurrentLinkedQueue
ConcurrentLinkedDeque

當多個執行緒共享訪問一個公共集合時,ConcurrentLinkedQueue 是一個恰當的選擇。ConcurrentLinkedQueue集合時無需等待。
在預設情況下,ConcurrentHashMap 支援16個執行緒併發寫入,當有超過16 個執行緒併發向該Map 中寫入資料時,可能有一些執行緒需要等待。實際上,程式通過設定concurrentLevel 構造引數(預設值為16)來支援更多的併發寫入執行緒。
與前面介紹的HashMap 和普通集合不同的是,因為ConcurrentLinkedQueue 和 ConcurrenthashMap 支援多執行緒併發訪問,所以當使用迭代來遍歷集合時,該迭代器可能不能反映出建立迭代器之後所做的修改,但程式不會丟擲任何異常。

3、以CopyOnWrite 開頭的集合

看這張圖片右邊部分:
在這裡插入圖片描述

以CopyOnWrite 開頭的集合類,如
CopyOnWriteArrayList
CopyOnWriteArraySet。

CopyOnWrite容器即寫時複製的容器。
通俗的理解是當我們往一個容器新增元素的時候,不直接往當前容器新增,而是先將當前容器進行Copy,複製出一個新的容器,然後新的容器裡新增元素,新增完元素之後,再將原容器的引用指向新的容器。

這樣做的好處是我們可以對CopyOnWrite容器進行併發的讀,而不需要加鎖,因為當前容器不會新增任何元素。所以CopyOnWrite容器也是一種讀寫分離的思想,讀和寫不同的容器。

一般面試中說出這些分類和各自的理解,面試官會眉開眼笑哦!