Java并發(fā)編程(十) LinkedBlockingQueue

下面我們來說一下java中的BlockingQueue承绸。先來看一下BlockingQueue都有哪些方法
offer(E e): 將給定的元素設(shè)置到隊(duì)列中屑彻,如果設(shè)置成功返回true, 否則返回false. e的值不能為空亿絮,否則拋出空指針異常卵蛉。
offer(E e, long timeout, TimeUnit unit): 將給定元素在給定的時(shí)間內(nèi)設(shè)置到隊(duì)列中娘纷,如果設(shè)置成功返回true, 否則返回false.
add(E e): 將給定元素設(shè)置到隊(duì)列中回铛,如果設(shè)置成功返回true, 否則拋出異常狗准。如果是往限定了長度的隊(duì)列中設(shè)置值,推薦使用offer()方法茵肃。
put(E e): 將元素設(shè)置到隊(duì)列中腔长,如果隊(duì)列中沒有多余的空間,該方法會(huì)一直阻塞验残,直到隊(duì)列中有多余的空間捞附。
take(): 從隊(duì)列中獲取值,如果隊(duì)列中沒有值,線程會(huì)一直阻塞鸟召,直到隊(duì)列中有值胆绊,并且該方法取得了該值。
poll(long timeout, TimeUnit unit): 在給定的時(shí)間里欧募,從隊(duì)列中獲取值压状,如果沒有取到會(huì)拋出異常。
remove(Object o): 從隊(duì)列中移除指定的值跟继。
contains(Object o): 判斷隊(duì)列中是否擁有該值种冬。
put和take方法是阻塞的。下面我們就來看一下LinkedBlockingQueue是怎么實(shí)現(xiàn)的舔糖。
LinkedBlockingQueue是基于鏈表實(shí)現(xiàn)的娱两,我們來看一下LinkedBlockingQueue都有哪些屬性

/** The capacity bound, or Integer.MAX_VALUE if none */
private final int capacity;

/** Current number of elements */
private final AtomicInteger count = new AtomicInteger();

/**
 * Head of linked list.
 * Invariant: head.item == null
 */
transient Node<E> head;

/**
 * Tail of linked list.
 * Invariant: last.next == null
 */
private transient Node<E> last;

/** Lock held by take, poll, etc */
private final ReentrantLock takeLock = new ReentrantLock();

/** Wait queue for waiting takes */
private final Condition notEmpty = takeLock.newCondition();

/** Lock held by put, offer, etc */
private final ReentrantLock putLock = new ReentrantLock();

/** Wait queue for waiting puts */
private final Condition notFull = putLock.newCondition();

有一個(gè)head,保存首節(jié)點(diǎn)的引用剩盒,一個(gè)last,保存尾節(jié)點(diǎn)的引用慨蛙,還有一個(gè)tabkLock和Condition辽聊,用來在take操作的時(shí)候阻塞線程的,一個(gè)putLock和Condition期贫,用來在put操作的時(shí)候阻塞線程的跟匆。
LinkedBlockingQueue有一個(gè)內(nèi)部類Node,有一個(gè)屬性item通砍,代表元素玛臂,一個(gè)Node元素的next,代表下一個(gè)節(jié)點(diǎn)

static class Node<E> {
    E item;

    /**
     * One of:
     * - the real successor Node
     * - this Node, meaning the successor is head.next
     * - null, meaning there is no successor (this is the last node)
     */
    Node<E> next;

    Node(E x) { item = x; }
}

下面我們來看一下put方法

public void put(E e) throws InterruptedException {
    if (e == null) throw new NullPointerException();
    // Note: convention in all put/take/etc is to preset local var
    // holding count negative to indicate failure unless set.
    int c = -1;
    Node<E> node = new Node<E>(e);
    final ReentrantLock putLock = this.putLock;
    final AtomicInteger count = this.count;
    putLock.lockInterruptibly();
    try {
        /*
         * Note that count is used in wait guard even though it is
         * not protected by lock. This works because count can
         * only decrease at this point (all other puts are shut
         * out by lock), and we (or some other waiting put) are
         * signalled if it ever changes from capacity. Similarly
         * for all other uses of count in other wait guards.
         */
        while (count.get() == capacity) {
            notFull.await();
        }
        enqueue(node);
        c = count.getAndIncrement();
        if (c + 1 < capacity)
            notFull.signal();
    } finally {
        putLock.unlock();
    }
    if (c == 0)
        signalNotEmpty();
}

先將值放到Node節(jié)點(diǎn)中封孙,然后上鎖迹冤,如果當(dāng)前隊(duì)列的數(shù)量等于容量,則調(diào)用await方法阻塞等待虎忌,否則進(jìn)行入隊(duì)操作泡徙,然后如果隊(duì)列的數(shù)量小于容量,則喚醒等待的線程繼續(xù)執(zhí)行膜蠢,然后解鎖堪藐,如果隊(duì)列的數(shù)量為0,則喚醒take操作阻塞的線程
再來看一下take方法

public E take() throws InterruptedException {
    E x;
    int c = -1;
    final AtomicInteger count = this.count;
    final ReentrantLock takeLock = this.takeLock;
    takeLock.lockInterruptibly();
    try {
        while (count.get() == 0) {
            notEmpty.await();
        }
        x = dequeue();
        c = count.getAndDecrement();
        if (c > 1)
            notEmpty.signal();
    } finally {
        takeLock.unlock();
    }
    if (c == capacity)
        signalNotFull();
    return x;
}

先上鎖挑围,然后判斷如果隊(duì)列數(shù)量等于0礁竞,則阻塞當(dāng)前線程,否則從隊(duì)列中取出元素杉辙,如果隊(duì)列的數(shù)量大于0模捂,則喚醒被阻塞的線程繼續(xù)執(zhí)行,然后解鎖,如果隊(duì)列的數(shù)量等于容量-1枫绅,則喚醒put操作阻塞的線程
LinkedBlockingQueue就分析到這里了泉孩。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市并淋,隨后出現(xiàn)的幾起案子寓搬,更是在濱河造成了極大的恐慌泽疆,老刑警劉巖旨别,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件滥朱,死亡現(xiàn)場(chǎng)離奇詭異钢坦,居然都是意外死亡苗胀,警方通過查閱死者的電腦和手機(jī)洽洁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門团秽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來疯趟,“玉大人澎剥,你說我怎么就攤上這事锡溯。” “怎么了哑姚?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵祭饭,是天一觀的道長。 經(jīng)常有香客問我叙量,道長倡蝙,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任绞佩,我火速辦了婚禮寺鸥,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘品山。我一直安慰自己胆建,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布肘交。 她就那樣靜靜地躺著眼坏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪酸些。 梳的紋絲不亂的頭發(fā)上宰译,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音魄懂,去河邊找鬼沿侈。 笑死,一個(gè)胖子當(dāng)著我的面吹牛市栗,可吹牛的內(nèi)容都是我干的缀拭。 我是一名探鬼主播咳短,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼蛛淋!你這毒婦竟也來了咙好?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤褐荷,失蹤者是張志新(化名)和其女友劉穎勾效,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體叛甫,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡层宫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了其监。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片萌腿。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖抖苦,靈堂內(nèi)的尸體忽然破棺而出毁菱,到底是詐尸還是另有隱情,我是刑警寧澤锌历,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布贮庞,位于F島的核電站,受9級(jí)特大地震影響辩涝,放射性物質(zhì)發(fā)生泄漏贸伐。R本人自食惡果不足惜勘天,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一怔揩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧脯丝,春花似錦商膊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至材蹬,卻和暖如春实幕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背堤器。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國打工昆庇, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人闸溃。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓整吆,卻偏偏與公主長得像拱撵,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子表蝙,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容