java多線程-03-阻塞隊列簡介

[TOC]

聲明

該系列文章只是記錄本人回顧java多線程編程時候記錄的筆記拱燃。文中所用語言并非嚴謹?shù)膶I(yè)術(shù)語(太嚴謹?shù)男g(shù)語其實本人也不會……)碗誉。難免有理解偏差的地方,歡迎指正弄跌。
另外尝苇,大神請繞路糠溜。不喜勿噴。
畢竟好記性不如爛筆頭嘛蜕着,而且許多東西只要不是你經(jīng)常用的最終都會一丟丟一丟丟地給忘記豹芯。

** 初看之下宽闲,阻塞隊列似乎和多線程沒有多大關(guān)系沿腰。但是平時使用阻塞隊列的場景往往是和線程相關(guān)的纽什。所以枫慷,此處將阻塞隊列也歸入java多線程的分類探孝。 **

1 什么是阻塞隊列

說白了找御,阻塞隊列還是一個隊列(FIFO)讨永。至于隊列的概念就不多說了揭糕。
阻塞隊列和普通隊列的區(qū)別就在阻塞這個詞吏口。

阻塞的意思,可以這么理解:

  • 當嘗試隊列出隊操作時舟铜,若隊列已經(jīng)是空的谆刨,則調(diào)用出隊操作的線程將被阻塞血柳,直到隊列有可用元素為止
  • 當嘗試隊列入隊操作時难捌,若隊列已經(jīng)是滿的,則調(diào)用入隊操作的線程將被阻塞击敌,直到隊列不再是滿的為止

2 JDK提供的阻塞隊列

2.1 JDK內(nèi)置的阻塞隊列

  • ArrayBlockingQueue: 數(shù)組結(jié)構(gòu)的有界阻塞隊列
  • LinkedBlockingQueue: 鏈表結(jié)構(gòu)的有界阻塞隊列
  • LinkedTransferQueue: 鏈表結(jié)構(gòu)的無界阻塞隊列
  • LinkedBlockingDeque: 鏈表結(jié)構(gòu)的雙向阻塞隊列
  • PriorityBlockingQueue: 支持按優(yōu)先級排序的無界阻塞隊列
  • DelayQueue: 使用優(yōu)先級隊列(PriorityQueue)實現(xiàn)的阻塞隊列刃宵,優(yōu)先隊列的比較基準值是時間
  • SynchronousQueue: 不知道怎么描述這個隊列,因為他并不真正存儲元素牲证。每個插入操作必須等待另一個線程的移除操作十厢,同樣一個移除操作都等待另一個線程的插入操作。

2.2 阻塞隊列不可用時的處理方式

此處要說的是筛武,隊列在特殊情況下的出隊入隊操作的處理榴都。
比如在隊列為空或者隊列已經(jīng)滿了的時候不同的阻塞隊列實現(xiàn)或者不同的方法會有不同的處理方式竿音。

對這種特殊情況的處理柴信,大致有以下一些方法:

  • 拋異常
    • 隊列為空時進行出隊操作,可能會有NoSuchElementException
    • 隊列已滿時進行入隊操作,可能會有IllegalStateException
  • 返回特殊值
    • 拋出NoSuchElementException,可以返回null代替表示隊列為空
    • 拋出IllegalStateException,可以返回false表示入隊失敗
  • 一直阻塞
    • 隊列為空時進行出隊操作,進行出隊操作的線程將被阻塞,直至隊列可用
    • 隊列已滿時進行入隊操作,進行入隊操作的線程將被阻塞,直至隊列可用
  • 超時退出
    • 隊列為空時進行出隊操作,進行出隊操作的線程將被阻塞,直至超時退出(線程也會退出)
    • 隊列已滿時進行入隊操作,進行入隊操作的線程將被阻塞,直至超時退出(線程也會退出)

以下圖片是來自《Java并發(fā)編程的藝術(shù)》一書中的總結(jié):

這隊列特殊情況的處理

3 使用示例

以上介紹的七種JDK內(nèi)置的阻塞隊列,各有各的使用場景,一篇文章很難介紹清楚序目。
以后會抽空補全各種阻塞隊列的使用場景示例逗旁。

此處英古,就修改一下上篇文章線程通信中那個生產(chǎn)者和消費者的示例程序(http://blog.csdn.net/hylexus/article/details/53446711)。

和上篇文章的不同之處在于艺沼,此處使用阻塞隊列來代替上篇文章中簡單實現(xiàn)的一個數(shù)據(jù)結(jié)構(gòu)棧调鲸。
Container類的實現(xiàn)修改成了下面的樣子:

public static class Container {
    private ArrayBlockingQueue<Product> products;

    public Container(int size) {
        this.products = new ArrayBlockingQueue<>(size);
    }

    public void put(Product product) {
        try {
            this.products.put(product);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public Product get() {
        try {
            return this.products.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return null;
    }
}

完整的代碼示例如下:

import java.util.concurrent.ArrayBlockingQueue;

public class ProducerConsumerByLockingQueue {

    public static void main(String[] args) {
        Container container = new Container(5);
        for (int i = 0; i < 10; i++) {
            new Thread(new Producer(container), "P-" + i).start();
            new Thread(new Consumer(container), "C-" + i).start();
        }
    }

    public static class Product {
        private String name;

        public Product(String name) {
            super();
            this.name = name;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        @Override
        public String toString() {
            return "[name=" + name + "]";
        }

    }

    public static class Container {
        private ArrayBlockingQueue<Product> products;

        public Container(int size) {
            this.products = new ArrayBlockingQueue<>(size);
        }

        public void put(Product product) {
            try {
                this.products.put(product);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        public Product get() {
            try {
                return this.products.take();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

    public static class Producer implements Runnable {

        private Container container;

        public Producer(Container container) {
            super();
            this.container = container;
        }

        @Override
        public void run() {
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                Product p = new Product(Thread.currentThread().getName() + "_" + i);
                this.container.put(p);
                System.out.println("生產(chǎn)者[" + Thread.currentThread().getName() + "]生產(chǎn)>>>>>>:" + p);
                try {
                    Thread.sleep((long) (Math.random() * 1000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public static class Consumer implements Runnable {

        private Container container;

        public Consumer(Container container) {
            super();
            this.container = container;
        }

        @Override
        public void run() {
            for (int i = 0; i < Integer.MAX_VALUE; i++) {
                Product product = this.container.get();
                System.out.println("消費者[" + Thread.currentThread().getName() + "]消費<<<<<<:" + product);
                try {
                    Thread.sleep((long) (Math.random() * 2000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}

參考資料

  • 《java并發(fā)編程的藝術(shù)》
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末角雷,一起剝皮案震驚了整個濱河市祸穷,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌勺三,老刑警劉巖雷滚,帶你破解...
    沈念sama閱讀 219,589評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異吗坚,居然都是意外死亡祈远,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評論 3 396
  • 文/潘曉璐 我一進店門商源,熙熙樓的掌柜王于貴愁眉苦臉地迎上來车份,“玉大人,你說我怎么就攤上這事牡彻∩ㄕ樱” “怎么了?”我有些...
    開封第一講書人閱讀 165,933評論 0 356
  • 文/不壞的土叔 我叫張陵庄吼,是天一觀的道長缎除。 經(jīng)常有香客問我,道長总寻,這世上最難降的妖魔是什么器罐? 我笑而不...
    開封第一講書人閱讀 58,976評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮渐行,結(jié)果婚禮上轰坊,老公的妹妹穿的比我還像新娘。我一直安慰自己祟印,他們只是感情好肴沫,可當我...
    茶點故事閱讀 67,999評論 6 393
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著蕴忆,像睡著了一般樊零。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,775評論 1 307
  • 那天驻襟,我揣著相機與錄音夺艰,去河邊找鬼。 笑死沉衣,一個胖子當著我的面吹牛郁副,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播豌习,決...
    沈念sama閱讀 40,474評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼飞主,長吁一口氣:“原來是場噩夢啊……” “哼啡专!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,359評論 0 276
  • 序言:老撾萬榮一對情侶失蹤穆律,失蹤者是張志新(化名)和其女友劉穎鸣皂,沒想到半個月后恢准,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體戳气,經(jīng)...
    沈念sama閱讀 45,854評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,007評論 3 338
  • 正文 我和宋清朗相戀三年吸占,在試婚紗的時候發(fā)現(xiàn)自己被綠了晴叨。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,146評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡矾屯,死狀恐怖兼蕊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情件蚕,我是刑警寧澤孙技,帶...
    沈念sama閱讀 35,826評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站排作,受9級特大地震影響牵啦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜纽绍,卻給世界環(huán)境...
    茶點故事閱讀 41,484評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望势似。 院中可真熱鬧拌夏,春花似錦、人聲如沸履因。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽栅迄。三九已至站故,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背西篓。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評論 1 272
  • 我被黑心中介騙來泰國打工愈腾, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人岂津。 一個月前我還...
    沈念sama閱讀 48,420評論 3 373
  • 正文 我出身青樓虱黄,卻偏偏與公主長得像,于是被迫代替她去往敵國和親吮成。 傳聞我的和親對象是個殘疾皇子橱乱,可洞房花燭夜當晚...
    茶點故事閱讀 45,107評論 2 356

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