java併發容器

CopyOnWriteArrayList
  併發容器,底層數組,讀寫分離,適合讀大於寫的操作,迭代器和加強for循環不會ConcurrentModificationException異常
  修改/添加/刪除時複製(淺複製)新的數組,使用新的數組,查詢和迭代時使用老的數組(使用老的for循環會出現異常),迭代時和修改/添加/刪除時使用不同的數據源
  修改/添加/刪除時加鎖,讀不加鎖
  CopyOnWriteArraySet
類似於CopyOnWriteArrayList,底層使用CopyOnWriteArrayList
不允許重複
CopyOnWrite容器有很多優點,但是同時也存在兩個問題,即內存佔用問題和數據一致性問題。
1.保持最終一致性 2.在修改時複製了新數組,所以內存中存在多個數組

concurrenthashmap
底層數組+hash結構
原理鎖分段,用new object[16]中每個元素作爲一個鎖,然後用synchronized(object[hash(key)%16])進行同步
ConcurrentMap接口中增加了一些常見的複合操作的支持。對ConcurrentHashMap進行迭代不會拋出異常(弱一致性)。
size,isEnptry這些方法的語意被減弱了以反映容器的併發特性,還包括(get、put、containsKey、remove)
ConcurrentHashMap的弱一致性主要是爲了提升效率,是一致性與效率之間的一種權衡。要成爲強一致性,就得到處使用鎖,甚至是全局鎖,這就與Hashtable和同步的HashMap一樣了。

ConcurrentLinkedQueue
鏈表的、無界的安全隊列 
併發隊列 先進先出 非阻塞隊列
ConcurrentLinkedQueue的API原來.size()是要遍歷一遍集合的,所以儘量要避免用size而改用isEmpty()
隊列不允許null元素

LinkedBlockingQueue
基於鏈表的阻塞隊列,其內部也維持着一個數據緩衝隊列(該隊列由一個鏈表構成),
當生產者往隊列中放入一個數據時,隊列會從生產者手中獲取數據,並緩存在隊列內部,而生產者立即返回;
只有當隊列緩衝區達到最大值緩存容量時(LinkedBlockingQueue可以通過構造函數指定該值),
纔會阻塞生產者隊列,直到消費者從隊列中消費掉一份數據,生產者線程會被喚醒,反之對於消費者這端的處理也基於同樣的原理。
而LinkedBlockingQueue之所以能夠高效的處理併發數據,還因爲其對於生產者端和消費者端分別採用了獨立的鎖來控制數據同步,
這也意味着在高併發的情況下生產者和消費者可以並行地操作隊列中的數據,以此來提高整個隊列的併發性能。
作爲開發者,我們需要注意的是,如果構造一個LinkedBlockingQueue對象,而沒有指定其容量大小,
LinkedBlockingQueue會默認一個類似無限大小的容量(Integer.MAX_VALUE),
這樣的話,如果生產者的速度一旦大於消費者的速度,也許還沒有等到隊列滿阻塞產生,系統內存就有可能已被消耗殆盡了。

ArrayBlockingQueue
ArrayBlockingQueue是一個由數組支持的有界阻塞隊列。此隊列按 FIFO(先進先出)原則對元素進行排序。
隊列的頭部 是在隊列中存在時間最長的元素,隊列的尾部 是在隊列中存在時間最短的元素。
新元素插入到隊列的尾部,隊列檢索操作則是從隊列頭部開始獲得元素。
         這是一個典型的“有界緩存區”,固定大小的數組在其中保持生產者插入的元素和使用者提取的元素。
         一旦創建了這樣的緩存區,就不能再增加其容量。試圖向已滿隊列中放入元素會導致放入操作受阻塞;
        試圖從空隊列中檢索元素將導致類似阻塞。
   ArrayBlockingQueue創建的時候需要指定容量capacity(可以存儲的最大的元素個數,因爲它不會自動擴容)。

  PriorityBlockingQueue
        類似於LinkedBlockQueue,但其所含對象的排序不是FIFO,而是依據對象的自然排序順序或者是構造函數的Comparator決定的順序
  
  SynchronousQueue
  Java 6的併發編程包中的SynchronousQueue是一個沒有數據緩衝的BlockingQueue,
       生產者線程對其的插入操作put必須等待消費者的移除操作take,反過來也一樣。
        不像ArrayBlockingQueue或LinkedListBlockingQueue,SynchronousQueue內部並沒有數據緩存空間,
        你不能調用peek()方法來看隊列中是否有數據元素,因爲數據元素只有當你試着取走的時候纔可能存在,
        不取走而只想偷窺一下是不行的,當然遍歷這個隊列的操作也是不允許的。隊列頭元素是第一個排隊要插入數據的線程,
        而不是要交換的數據。數據是在配對的生產者和消費者線程之間直接傳遞的,並不會將數據緩衝數據到隊列中。
        可以這樣來理解:生產者和消費者互相等待對方,握手,然後一起離開。
        
linkedblockingdeque
  雙向併發阻塞隊列。所謂雙向是指可以從隊列的頭和尾同時操作,併發只是線程安全的實現,
  阻塞允許在入隊出隊不滿足條件時掛起線程,這裏說的隊列是指支持FIFO/FILO實現的鏈表。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章