Java阻塞隊(duì)列

image

JAVA中的幾種主要的阻塞隊(duì)列

  1. ArrayBlockingQueue: 基于數(shù)組實(shí)現(xiàn)的一個(gè)阻塞隊(duì)列榕订,在創(chuàng)建ArrayBlockingQueue對象必須指定容量大小渤滞。并且可以指定公平性和非公平性苏潜,默認(rèn)情況下為非公平性,即不保存等待時(shí)間最長的隊(duì)列有限能夠訪問隊(duì)列耕漱。
  2. LinkedBlockingQueue: 基于鏈表實(shí)現(xiàn)的一個(gè)阻塞隊(duì)列龙优,在創(chuàng)建LinkedBlockingQueue對象如果不指定容量大小,則為Integer.MAX_VALUE.
  3. PriorityBlockingQueue: 以上2種隊(duì)列都是先進(jìn)先出隊(duì)列浇借,而PriorityBlockQueue卻不是捉撮,它會按照元素的優(yōu)先級對元素進(jìn)行排序,按照優(yōu)先級順序出隊(duì)妇垢,每次出隊(duì)的元素都是優(yōu)先級最高的元素巾遭。注意,此阻塞隊(duì)列為無界阻塞隊(duì)列闯估,即容量沒有上限灼舍。
  4. DelayQueue: 基于PriorityBlockingQueue: 基于PriortyQueue, 一種延時(shí)阻塞隊(duì)列,DelayQueue中的元素只有當(dāng)其指定的延遲時(shí)間到了涨薪,才能夠從隊(duì)列中獲取到該元素骑素。DelayQueue也是一種無界隊(duì)列,因此往隊(duì)列中插入數(shù)據(jù)的操作(生產(chǎn)者)永遠(yuǎn)不會被阻塞刚夺,而只有獲取數(shù)據(jù)的操作(消費(fèi)者)才會被阻塞献丑。

阻塞隊(duì)列的幾個(gè)方法

  1. put(E e): 向隊(duì)尾存入元素,如果隊(duì)列滿了侠姑,則等待创橄。
  2. tack(): 從隊(duì)首取元素,如果隊(duì)伍為空莽红,則等待妥畏。
  3. offer(E e, long timeout, TimeUnil unit): 如果隊(duì)列滿了則等待一定時(shí)間,沒有插入成功則返回false,成功則返回true.
  4. poll(long timeout, TimeUnit unit): 如果隊(duì)列為空安吁,則等待一定時(shí)間醉蚁,當(dāng)時(shí)間期限達(dá)到時(shí),如果未取到柳畔,則返回null.

實(shí)現(xiàn)

  • 阻塞隊(duì)列實(shí)現(xiàn)
public class BlockingQueue {
    private List<Object> queue = new LinkedList<>();
    private int limit = 10;

    public BlockingQueue(int limit){
        this.limit = limit;
    }
    
    /**
     * 當(dāng)隊(duì)列滿了的時(shí)候阻塞線程
     *
     * @param item
     * @throws InterruptedException
     */
    public synchronized void enqueue(Object item) throws InterruptedException {
        while (this.queue.size() == this.limit) {
            wait();
        }
        if (this.queue.size() < this.limit) {
            notifyAll();
        }
        this.queue.add(item);
    }

    /**
     * 當(dāng)隊(duì)列為空的時(shí)候阻塞線程
     * @return
     * @throws InterruptedException
     */
    public synchronized Object dequeue() throws InterruptedException {
        while (this.queue.size() == 0) {
            wait();
        }
        if (this.queue.size() > 1) {
            notifyAll();
        }
        return this.queue.remove(0);
    }
}

  • 使用阻塞隊(duì)列實(shí)現(xiàn)生產(chǎn)者消費(fèi)者
public class ProducerConsumerPattern {

    public static void main(String[] args) {
        BlockingQueue shareQueue = new LinkedBlockingQueue<>();

        Thread prodThread = new Thread(new Producer(shareQueue));
        Thread consThread = new Thread(new Consumer(shareQueue));

        prodThread.start();
        consThread.start();
    }
    
    /**
     * 生產(chǎn)者
     */
    static class Producer implements Runnable {
        private final BlockingQueue shareQueue;
        public Producer(BlockingQueue shareQueue) {
            this.shareQueue = shareQueue;
        }

        @Override
        public void run() {
            for (int i = 0; i < 10; i++){
                System.out.println("Produced: " + i);
                try {
                    shareQueue.put(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 消費(fèi)者
     */
    static class Consumer implements Runnable {
        private final java.util.concurrent.BlockingQueue shareQueue;
        public Consumer(BlockingQueue shareQueue) {
            this.shareQueue = shareQueue;
        }

        @Override
        public void run() {
            while (true) {
                try {
                    System.out.println("Consumer: " + shareQueue.take());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
  • 使用Lock和Condition實(shí)現(xiàn)阻塞隊(duì)列
public class BoundedBuffer {
    final Lock lock = new ReentrantLock();
    final Condition notFull = lock.newCondition();
    final Condition notEmpty = lock.newCondition();

    final Object[] items = new Object[100];

    int putptr, takeptr, count;

    public void put(Object x) throws InterruptedException {
        lock.lock();
        try {
            while (count == items.length)
                notFull.await();
            items[putptr] = x;
            if (++putptr == items.length)
                putptr = 0;
            ++count;
            notEmpty.signal();
        } finally {
            lock.unlock();
        }
    }

    public Object take() throws InterruptedException {
        lock.lock();
        try {
            while (count == 0)
                notEmpty.await();
            Object x = items[takeptr];
            if (++takeptr == items.length)
                takeptr = 0;
            --count;
            notFull.signal();
            return x;
        } finally {
            lock.unlock();
        }
    }
}

源碼傳送門

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末馍管,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子薪韩,更是在濱河造成了極大的恐慌确沸,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俘陷,死亡現(xiàn)場離奇詭異罗捎,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)拉盾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門桨菜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事倒得⌒汉欤” “怎么了?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵霞掺,是天一觀的道長谊路。 經(jīng)常有香客問我,道長菩彬,這世上最難降的妖魔是什么缠劝? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮骗灶,結(jié)果婚禮上惨恭,老公的妹妹穿的比我還像新娘。我一直安慰自己耙旦,他們只是感情好脱羡,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著母廷,像睡著了一般轻黑。 火紅的嫁衣襯著肌膚如雪糊肤。 梳的紋絲不亂的頭發(fā)上琴昆,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天,我揣著相機(jī)與錄音馆揉,去河邊找鬼业舍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛升酣,可吹牛的內(nèi)容都是我干的舷暮。 我是一名探鬼主播,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼噩茄,長吁一口氣:“原來是場噩夢啊……” “哼下面!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起绩聘,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤沥割,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后凿菩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體机杜,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年衅谷,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了椒拗。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,754評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蚀苛,靈堂內(nèi)的尸體忽然破棺而出在验,到底是詐尸還是另有隱情,我是刑警寧澤堵未,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布译红,位于F島的核電站,受9級特大地震影響兴溜,放射性物質(zhì)發(fā)生泄漏侦厚。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一拙徽、第九天 我趴在偏房一處隱蔽的房頂上張望刨沦。 院中可真熱鬧,春花似錦膘怕、人聲如沸想诅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽来破。三九已至,卻和暖如春忘古,著一層夾襖步出監(jiān)牢的瞬間徘禁,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工髓堪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留送朱,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓干旁,卻偏偏與公主長得像驶沼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子争群,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評論 2 354

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

  • 定義 阻塞隊(duì)列是一個(gè)支持兩個(gè)附加操作的隊(duì)列回怜,即:在隊(duì)列為空時(shí),獲取元素的線程會等待隊(duì)列變?yōu)榉强栈槐 .?dāng)隊(duì)列滿時(shí)玉雾,存儲元...
    忘凈空閱讀 560評論 0 0
  • 阻塞隊(duì)列(BlockingQueue)是一個(gè)支持兩個(gè)附加操作的隊(duì)列。這兩個(gè)附加的操作是:在隊(duì)列為空時(shí)专控,獲取元素的線...
    堤岸小跑閱讀 378評論 0 2
  • 相關(guān)文章Java并發(fā)編程(一)線程定義抹凳、狀態(tài)和屬性 Java并發(fā)編程(二)同步Java并發(fā)編程(三)volatil...
    劉望舒閱讀 5,235評論 1 31
  • 阻塞隊(duì)列(BlockingQueue)是一個(gè)支持兩個(gè)附加操作的隊(duì)列。這兩個(gè)附加的操作是:在隊(duì)列為空時(shí)伦腐,獲取元素的線...
    端木軒閱讀 1,004評論 0 2
  • I’m justa sunflower,waiting for my only sunshine .從南方回來赢底,...
    十胖x閱讀 465評論 0 1