成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

什么是阻塞隊列?如何使用阻塞隊列來實現(xiàn)生產(chǎn)者-消費者模型?

jemygraw / 3528人閱讀

摘要:什么是阻塞隊列阻塞隊列是一個在隊列基礎(chǔ)上又支持了兩個附加操作的隊列。阻塞隊列的應(yīng)用場景阻塞隊列常用于生產(chǎn)者和消費者的場景,生產(chǎn)者是向隊列里添加元素的線程,消費者是從隊列里取元素的線程。由鏈表結(jié)構(gòu)組成的無界阻塞隊列。

什么是阻塞隊列?

阻塞隊列是一個在隊列基礎(chǔ)上又支持了兩個附加操作的隊列。

2個附加操作:

支持阻塞的插入方法:隊列滿時,隊列會阻塞插入元素的線程,直到隊列不滿。

支持阻塞的移除方法:隊列空時,獲取元素的線程會等待隊列變?yōu)榉强铡?/p> 阻塞隊列的應(yīng)用場景

阻塞隊列常用于生產(chǎn)者和消費者的場景,生產(chǎn)者是向隊列里添加元素的線程,消費者是從隊列里取元素的線程。簡而言之,阻塞隊列是生產(chǎn)者用來存放元素、消費者獲取元素的容器。

幾個方法

在阻塞隊列不可用的時候,上述2個附加操作提供了四種處理方法

方法處理方式 拋出異常 返回特殊值 一直阻塞 超時退出
插入方法 add(e) offer(e) put(e) offer(e,time,unit)
移除方法 remove() poll() take() poll(time,unit)
檢查方法 element() peek() 不可用 不可用
JAVA里的阻塞隊列

JDK 7 提供了7個阻塞隊列,如下

1、ArrayBlockingQueue 數(shù)組結(jié)構(gòu)組成的有界阻塞隊列。

此隊列按照先進(jìn)先出(FIFO)的原則對元素進(jìn)行排序,但是默認(rèn)情況下不保證線程公平的訪問隊列,即如果隊列滿了,那么被阻塞在外面的線程對隊列訪問的順序是不能保證線程公平(即先阻塞,先插入)的。

2、LinkedBlockingQueue一個由鏈表結(jié)構(gòu)組成的有界阻塞隊列

此隊列按照先出先進(jìn)的原則對元素進(jìn)行排序

3、PriorityBlockingQueue 支持優(yōu)先級的無界阻塞隊列

4、DelayQueue 支持延時獲取元素的無界阻塞隊列,即可以指定多久才能從隊列中獲取當(dāng)前元素

5、SynchronousQueue不存儲元素的阻塞隊列,每一個put必須等待一個take操作,否則不能繼續(xù)添加元素。并且他支持公平訪問隊列。

6、LinkedTransferQueue由鏈表結(jié)構(gòu)組成的無界阻塞TransferQueue隊列。相對于其他阻塞隊列,多了tryTransfer和transfer方法

transfer方法

如果當(dāng)前有消費者正在等待接收元素(take或者待時間限制的poll方法),transfer可以把生產(chǎn)者傳入的元素立刻傳給消費者。如果沒有消費者等待接收元素,則將元素放在隊列的tail節(jié)點,并等到該元素被消費者消費了才返回。

tryTransfer方法

用來試探生產(chǎn)者傳入的元素能否直接傳給消費者。,如果沒有消費者在等待,則返回false。和上述方法的區(qū)別是該方法無論消費者是否接收,方法立即返回。而transfer方法是必須等到消費者消費了才返回。

7、LinkedBlockingDeque鏈表結(jié)構(gòu)的雙向阻塞隊列,優(yōu)勢在于多線程入隊時,減少一半的競爭。

如何使用阻塞隊列來實現(xiàn)生產(chǎn)者-消費者模型?

通知模式實現(xiàn):所謂通知模式,就是當(dāng)生產(chǎn)者往滿的隊列里添加元素時會阻塞住生產(chǎn)者,當(dāng)消費者消費了一個隊列中的元素后,會通知生產(chǎn)者當(dāng)前隊列可用。

使用BlockingQueue解決生產(chǎn)者消費者問題

為什么BlockingQueue適合解決生產(chǎn)者消費者問題

任何有效的生產(chǎn)者-消費者問題解決方案都是通過控制生產(chǎn)者put()方法(生產(chǎn)資源)和消費者take()方法(消費資源)的調(diào)用來實現(xiàn)的,一旦你實現(xiàn)了對方法的阻塞控制,那么你將解決該問題。

Java通過BlockingQueue提供了開箱即用的支持來控制這些方法的調(diào)用(一個線程創(chuàng)建資源,另一個消費資源)。java.util.concurrent包下的BlockingQueue接口是一個線程安全的可用于存取對象的隊列。

BlockingQueue是一種數(shù)據(jù)結(jié)構(gòu),支持一個線程往里存資源,另一個線程從里取資源。這正是解決生產(chǎn)者消費者問題所需要的,那么讓我們開始解決該問題吧。

生產(chǎn)者

以下代碼用于生產(chǎn)者線程

package io.ymq.example.thread;

import java.util.concurrent.BlockingQueue;

/**
 * 描述:生產(chǎn)者
 *
 * @author yanpenglei
 * @create 2018-03-14 15:52
 **/
class Producer implements Runnable {

    protected BlockingQueue queue;

    Producer(BlockingQueue theQueue) {
        this.queue = theQueue;
    }

    public void run() {
        try {
            while (true) {
                Object justProduced = getResource();
                queue.put(justProduced);
                System.out.println("生產(chǎn)者資源隊列大小= " + queue.size());
            }
        } catch (InterruptedException ex) {
            System.out.println("生產(chǎn)者 中斷");
        }
    }

    Object getResource() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException ex) {
            System.out.println("生產(chǎn)者 讀 中斷");
        }
        return new Object();
    }
}

消費者

以下代碼用于消費者線程

package io.ymq.example.thread;

import java.util.concurrent.BlockingQueue;

/**
 * 描述: 消費者
 *
 * @author yanpenglei
 * @create 2018-03-14 15:54
 **/
class Consumer implements Runnable {
    protected BlockingQueue queue;

    Consumer(BlockingQueue theQueue) {
        this.queue = theQueue;
    }

    public void run() {
        try {
            while (true) {
                Object obj = queue.take();
                System.out.println("消費者 資源 隊列大小 " + queue.size());
                take(obj);
            }
        } catch (InterruptedException ex) {
            System.out.println("消費者 中斷");
        }
    }

    void take(Object obj) {
        try {
            Thread.sleep(100); // simulate time passing
        } catch (InterruptedException ex) {
            System.out.println("消費者 讀 中斷");
        }
        System.out.println("消費對象 " + obj);
    }
}

測試該解決方案是否運行正常

package io.ymq.example.thread;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * 描述: 測試
 *
 * @author yanpenglei
 * @create 2018-03-14 15:58
 **/
public class ProducerConsumerExample {

    public static void main(String[] args) throws InterruptedException {

        int numProducers = 4;
        int numConsumers = 3;

        BlockingQueue myQueue = new LinkedBlockingQueue(5);

        for (int i = 0; i < numProducers; i++) {
            new Thread(new Producer(myQueue)).start();
        }

        for (int i = 0; i < numConsumers; i++) {
            new Thread(new Consumer(myQueue)).start();
        }

        Thread.sleep(1000);

        System.exit(0);
    }
}

運行結(jié)果

生產(chǎn)者資源隊列大小= 1
生產(chǎn)者資源隊列大小= 1
消費者 資源 隊列大小 1
生產(chǎn)者資源隊列大小= 1
消費者 資源 隊列大小 1
消費者 資源 隊列大小 1
生產(chǎn)者資源隊列大小= 1
生產(chǎn)者資源隊列大小= 3
消費對象 java.lang.Object@1e1aa52b
生產(chǎn)者資源隊列大小= 2
生產(chǎn)者資源隊列大小= 5
消費對象 java.lang.Object@6e740a76
消費對象 java.lang.Object@697853f6

......

消費對象 java.lang.Object@41a10cbc
消費對象 java.lang.Object@4963c8d1
消費者 資源 隊列大小 5
生產(chǎn)者資源隊列大小= 5
生產(chǎn)者資源隊列大小= 5
消費者 資源 隊列大小 4
消費對象 java.lang.Object@3e49c35d
消費者 資源 隊列大小 4
生產(chǎn)者資源隊列大小= 5

從輸出結(jié)果中,我們可以發(fā)現(xiàn)隊列大小永遠(yuǎn)不會超過5,消費者線程消費了生產(chǎn)者生產(chǎn)的資源

Contact

作者:鵬磊

出處:http://www.ymq.io

版權(quán)歸作者所有,轉(zhuǎn)載請注明出處

Wechat:關(guān)注公眾號,搜云庫,專注于開發(fā)技術(shù)的研究與知識分享

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/68788.html

相關(guān)文章

  • 想進(jìn)大廠?50個多線程面試題,你會多少?(一)

    摘要:下面是線程相關(guān)的熱門面試題,你可以用它來好好準(zhǔn)備面試。線程安全問題都是由全局變量及靜態(tài)變量引起的。持有自旋鎖的線程在之前應(yīng)該釋放自旋鎖以便其它線程可以獲得自旋鎖。 最近看到網(wǎng)上流傳著,各種面試經(jīng)驗及面試題,往往都是一大堆技術(shù)題目貼上去,而沒有答案。 不管你是新程序員還是老手,你一定在面試中遇到過有關(guān)線程的問題。Java語言一個重要的特點就是內(nèi)置了對并發(fā)的支持,讓Java大受企業(yè)和程序員...

    wow_worktile 評論0 收藏0
  • 支持生產(chǎn)阻塞的線程池

    摘要:參考類似的思路,最簡單的做法,我們可以直接定義一個,當(dāng)隊列滿時改為調(diào)用來實現(xiàn)生產(chǎn)者的阻塞這樣,我們就無需再關(guān)心和的邏輯,只要把精力集中在生產(chǎn)者和消費者線程的實現(xiàn)邏輯上,只管往線程池提交任務(wù)就行了。 在各種并發(fā)編程模型中,生產(chǎn)者-消費者模式大概是最常用的了。在實際工作中,對于生產(chǎn)消費的速度,通常需要做一下權(quán)衡。通常來說,生產(chǎn)任務(wù)的速度要大于消費的速度。一個細(xì)節(jié)問題是,隊列長度,以及如何匹...

    yunhao 評論0 收藏0
  • Java 隊列

    摘要:隊列中有元素時,就說明有過期了,線程繼續(xù)執(zhí)行,然后元素出隊,根據(jù)相應(yīng)的移除緩存。所以嚴(yán)格來說,雖然實現(xiàn)了隊列接口,但是它的目的卻并不是隊列,而是將生產(chǎn)者消費者線程配對。轉(zhuǎn)移隊列鏈?zhǔn)睫D(zhuǎn)移隊列。 引言 本周在編寫短信驗證碼頻率限制切面的時候,經(jīng)潘老師給的實現(xiàn)思路,使用隊列進(jìn)行實現(xiàn)。 看了看java.util包下的Queue接口,發(fā)現(xiàn)還從來沒用過呢! Collection集合類接口,由它派生...

    Pocher 評論0 收藏0
  • java 隊列

    摘要:是基于鏈接節(jié)點的線程安全的隊列。通過這些高效并且線程安全的隊列類,為我們快速搭建高質(zhì)量的多線程程序帶來極大的便利。隊列內(nèi)部僅允許容納一個元素。該隊列的頭部是延遲期滿后保存時間最長的元素。 隊列簡述 Queue: 基本上,一個隊列就是一個先入先出(FIFO)的數(shù)據(jù)結(jié)構(gòu)Queue接口與List、Set同一級別,都是繼承了Collection接口。LinkedList實現(xiàn)了Deque接 口。...

    goji 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<