java面試準備-併發包類
1.ConcurrentHashMap
ConcurrentHashMap其實就是執行緒安全版本的hashMap。簡單的解釋就是通過把整個Map分為N個Segment(類似HashTable),這樣每個HashTable之間就執行緒就不會發生衝突,可以提供相同的執行緒安全,但是效率提升N倍,預設提升16倍。
深度剖析ConcurrentHashMap
ConcurrentHashMap原理分析
2.CopyOnWriteArrayList
-
CopyOnWriteArrayList是執行緒安全版本的ArrayList。
-
什麼是CopyOnWrite容器(寫的時候複製)
CopyOnWrite容器即寫時複製的容器。通俗的理解是當我們往一個容器新增元素的時候,不直接往當前容器新增,而是先將當前容器進行Copy,複製出一個新的容器,然後新的容器裡新增元素,新增完元素之後,再將原容器的引用指向新的容器。這樣做的好處是我們可以對CopyOnWrite容器進行併發的讀,而不需要加鎖,因為當前容器不會新增任何元素。所以CopyOnWrite容器也是一種讀寫分離的思想,讀和寫不同的容器。 - CopyOnWriteArrayList的實現原理
在使用CopyOnWriteArrayList之前,我們先閱讀其原始碼瞭解下它是如何實現的。- 寫的時候:需要加鎖
以下程式碼是向CopyOnWriteArrayList中add方法的實現(向CopyOnWriteArrayList裡新增元素),可以發現在新增的時候是需要加鎖的,否則多執行緒寫的時候會Copy出N個副本出來。 - 讀的時候:不需要加鎖
讀的時候不需要加鎖,如果讀的時候有多個執行緒正在向CopyOnWriteArrayList新增資料,讀還是會讀到舊的資料,因為寫的時候不會鎖住舊的CopyOnWriteArrayList。
- 寫的時候:需要加鎖
- 相對於Arraylist執行緒安全,相對於vector,第一不會出現迭代器異常,第二提高了效率:
- 迭代器異常
java中,集合在遍歷的時候,如果內部被修改了會丟擲java.util.ConcurrentModificationException錯誤。list和vector都會丟擲 - 快速失敗
快速失敗是指某個執行緒在迭代vector的時候,不允許其他執行緒修改該vector的內容,這樣迭代器迭代出來的結果就會不準確,如用iterator迭代collection的時候,iterator就是另外起的一個執行緒,它去迭代collection,如果此時用collection.remove(obj)這個方法修改了collection裡面的內容的時候,就會出現ConcurrentModificationException異常,這時候該迭代器就快速失敗。
通俗解釋:就好像有一盤餃子,你要數數有幾個,在你還沒數完,其他人有放入(或拿走)了幾個餃子。
你就只能重新再數了。本來你數數就很快,但是,就有人比你手更快。 - 讀的效率提高了
由於都操作沒有加鎖,所以沒有執行緒衝突;但寫操作由於加鎖,並採取了複製,所以效率更加低。所以此方法適用於讀多寫少修改少的應用。
- 迭代器異常
一、阻塞佇列
- BlockingQueue.class,阻塞佇列介面
- BlockingDeque.class,雙端阻塞佇列介面
- ArrayBlockingQueue.class,阻塞佇列,陣列實現
- LinkedBlockingDeque.class,阻塞雙端佇列,連結串列實現
- LinkedBlockingQueue.class,阻塞佇列,連結串列實現
- DelayQueue.class,阻塞佇列,並且元素是Delay的子類,保證元素在達到一定時間後才可以取得到
- PriorityBlockingQueue.class,優先順序阻塞佇列
- SynchronousQueue.class,同步佇列,但是佇列長度為0,生產者放入佇列的操作會被阻塞,直到消費者過來取,所以這個佇列根本不需要空間存放元素;有點像一個獨木橋,一次只能一人通過,還不能在橋上停留
二、非阻塞佇列:
ConcurrentLinkedDeque.class,非阻塞雙端佇列,連結串列實現
ConcurrentLinkedQueue.class,非阻塞佇列,連結串列實現
三、轉移佇列:
TransferQueue.class,轉移佇列介面,生產者要等消費者消費的佇列,生產者嘗試把元素直接轉移給消費者
LinkedTransferQueue.class,轉移佇列的連結串列實現,它比SynchronousQueue更快
四、其它容器:
ConcurrentMap.class,併發Map的介面,定義了putIfAbsent(k,v)、remove(k,v)、replace(k,oldV,newV)、replace(k,v)這四個併發場景下特定的方法
ConcurrentHashMap.class,併發HashMap
ConcurrentNavigableMap.class,NavigableMap的實現類,返回最接近的一個元素
ConcurrentSkipListMap.class,它也是NavigableMap的實現類(要求元素之間可以比較),同時它比ConcurrentHashMap更加scalable——ConcurrentHashMap並不保證它的操作時間,並且你可以自己來調整它的load factor;但是ConcurrentSkipListMap可以保證O(log n)的效能,同時不能自己來調整它的併發引數,只有你確實需要快速的遍歷操作,並且可以承受額外的插入開銷的時候,才去使用它
ConcurrentSkipListSet.class,和上面類似,只不過map變成了set
CopyOnWriteArrayList.class,copy-on-write模式的array list,每當需要插入元素,不在原list上操作,而是會新建立一個list,適合讀遠遠大於寫並且寫時間並苛刻的場景
CopyOnWriteArraySet.class,和上面類似,list變成set而已