天天看點

Concurrent -- BlockingQueue -- ConcurrentHashMap

任何事做到極緻就是藝術 – 無雙

參考自 http://wsmajunfeng.iteye.com/blog/1629354

  • 在JDK 1.5 很重要的一點就是引入了并發包–Concurrent .*;其中BlockingQueue很好的解決了多線程高效安全“傳輸”資料的問題
  • BlockingQueue – 阻塞隊列(阻塞,在某些情況下會挂起線程(即阻塞),一旦條件滿足,被挂起的線程又會自動被喚醒)

    BlockingQueue的核心方法

    (1)poll(time):取走BlockingQueue裡排在首位的對象,若不能立即取出,則可以等time參數規定的時間,取不到時傳回null;

    (2)poll(long timeout, TimeUnit unit):從BlockingQueue取出一個隊首的對象,如果在指定時間内,隊列一旦有資料可取,則立即傳回隊列中的資料。否則知道時間

    逾時還沒有資料可取,傳回失敗。

    (3)take():取走BlockingQueue裡排在首位的對象,若BlockingQueue為空,阻斷進入等待狀态直到BlockingQueue有新的資料被加入;

    (4)drainTo():一次性從BlockingQueue擷取所有可用的資料對象(還可以指定擷取資料的個數),通過該方法,可以提升擷取資料效率;不需要多次分批加鎖或釋放鎖。

常見BlockingQueue

  1. ArrayBlockingQueue

    基于數組的阻塞隊列實作,生産者放入資料和消費者擷取資料,都是共用同一個鎖對象;建立ArrayBlockingQueue時,預設采用非公平鎖。

    2.LinkedBlockingQueue

    基于連結清單的阻塞隊列,生産者端和消費者端分别采用了獨立的鎖來控制資料同步,這也意味着在高并發的情況下生産者和消費者可以并行地操作隊列中的資料,以此來提高整個隊列的并發性能。構造一個LinkedBlockingQueue對象,而沒有指定其容量大小,LinkedBlockingQueue會預設一個類似無限大小的容量(Integer.MAX_VALUE)

  2. DelayQueue

    沒有大小限制的隊列,是以往隊列中插入資料的操作(生産者)永遠不會被阻塞,而隻有擷取資料的操作(消費者)才會被阻塞

  3. PriorityBlockingQueue

    基于優先級的阻塞隊列(優先級的判斷通過構造函數傳入的Compator對象來決定),實作PriorityBlockingQueue時,内部控制線程同步的鎖采用的是公平鎖

  4. SynchronousQueue

    一種無緩沖的等待隊列,聲明一個SynchronousQueue有兩種不同的方式,公平模式和非公平模式

ConcurrentHashMap

  • 底層采用分段的數組+連結清單實作,線程安全
  • 通過把整個Map分為N個Segment,可以提供相同的線程安全,但是效率提升N倍,預設提升16倍。(讀操作不加鎖,由于HashEntry的value變量是 volatile的,也能保證讀取到最新的值。)
  • Hashtable的synchronized是針對整張Hash表的,即每次鎖住整張表讓線程獨占,ConcurrentHashMap允許多個修改操作并發進行,其關鍵在于使用了鎖分離技術
  • 鎖分段技術:首先将資料分成一段一段的存儲,然後給每一段資料配一把鎖,當一個線程占用鎖通路其中一個段資料的時候,其他段的資料也能被其他線程通路。