最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java多線程案例之阻塞隊列詳解

 更新時間:2022年10月18日 14:55:48   作者:Moon?Bay  
阻塞隊列是一種特殊的隊列.?也遵守?“先進先出”?的原則.阻塞隊列能是一種線程安全的數(shù)據(jù)結(jié)構(gòu)。本文將通過一些示例為大家詳細講講阻塞隊列的原理與使用,感興趣的小伙伴可以學習一下

一.阻塞隊列介紹

1.1阻塞隊列特性

阻塞隊列特性:

一.安全性

二.產(chǎn)生阻塞效果

阻塞隊列是一種特殊的隊列. 也遵守 “先進先出” 的原則.阻塞隊列能是一種線程安全的數(shù)據(jù)結(jié)構(gòu), 并且具有以下特性:

  • 當隊列滿的時候, 繼續(xù)入隊列就會阻塞, 直到有其他線程從隊列中取走元素.
  • 當隊列空的時候, 繼續(xù)出隊列也會阻塞, 直到有其他線程往隊列中插入元素.

阻塞隊列的一個典型應用場景就是 “生產(chǎn)者消費者模型”. 這是一種非常典型的開發(fā)模型.

1.2阻塞隊列的優(yōu)點

我們可以將阻塞隊列比做成"生產(chǎn)者"和"消費者"的"交易平臺".

我們可以把這個模型來比做成"包餃子"

A 的作用是搟餃子皮,也就是"生產(chǎn)者"

B 的作用是包餃子,也就是"消費者"

X 的作用一個當作放搟好餃子皮的一個盤中,也就是阻塞隊列

這樣我們根據(jù)A,B,X可以想象以下場景

場景一:

當A搟餃子皮的速度過快,X被A的桿好餃子皮放滿了,這樣A就需要停止搟餃子皮這一個操作,這時只能等待B來利用A提供的餃子皮包餃子后X所空出的空間,來給A提供生產(chǎn)的環(huán)境

場景二:

當B包餃子的速度過快,X被B的包餃子所用的餃子皮用空,這樣B就需要停止包餃子這一個操作,這時只能等待A提供的餃子皮包餃子后X所存在餃子皮,來給B提供消費的環(huán)境

二.生產(chǎn)者消費者模型

生產(chǎn)者消費者模式就是通過一個容器來解決生產(chǎn)者和消費者的強耦合問題

生產(chǎn)者和消費者彼此之間不直接通訊,而通過阻塞隊列來進行通訊,所以生產(chǎn)者生產(chǎn)完數(shù)據(jù)之后不用等待消費者處理,直接扔給阻塞隊列,消費者不找生產(chǎn)者要數(shù)據(jù),而是直接從阻塞隊列里取

(1) 阻塞隊列就相當于一個緩沖區(qū),平衡了生產(chǎn)者和消費者的處理能力.

比如在 “秒殺” 場景下, 服務(wù)器同一時刻可能會收到大量的支付請求. 如果直接處理這些支付請求,服務(wù)器可能扛不住(每個支付請求的處理都需要比較復雜的流程). 這個時候就可以把這些請求都放到一個阻塞隊列中, 然后再由消費者線程慢慢的來處理每個支付請求.這樣做可以有效進行 “削峰”, 防止服務(wù)器被突然到來的一波請求直接沖垮.

(2) 阻塞隊列也能使生產(chǎn)者和消費者之間 解耦.

比如過年一家人一起包餃子. 一般都是有明確分工, 比如一個人負責搟餃子皮, 其他人負責包. 搟餃子皮的人就是 “生產(chǎn)者”, 包餃子的人就是 “消費者”.搟餃子皮的人不關(guān)心包餃子的人是誰(能包就行, 無論是手工包, 借助工具, 還是機器包), 包餃子的人也不關(guān)心搟餃子皮的人是誰(有餃子皮就行, 無論是用搟面杖搟的, 還是拿罐頭瓶搟, 還是直接從超市買的).

2.1阻塞隊列對生產(chǎn)者的優(yōu)化

優(yōu)化一:能夠讓多個服務(wù)器程序之間更充分的解耦合:

如果不使用生產(chǎn)者和消費者模型,此時A和B的耦合性比較強,如果A線程出現(xiàn)一些狀況B就會掛,B線程出現(xiàn)一些狀況A就會掛,這時當我們引入阻塞隊列后我們就可以將A,B線程分開,如果A,B線程掛了有阻塞隊列的存在下,是不會影響別的線程

優(yōu)化二:能夠?qū)τ谡埱筮M行"削峰填谷":

我們可以聯(lián)想到我國的三峽大壩,三峽大壩就相當于阻塞隊列,當我們遇到雨水大的季節(jié),我們就可以關(guān)閉三峽大壩,利用三峽大壩來存水;當我們遇到干旱期,我們就可以打開三峽大壩的門,來放水解決干旱問題

三.標準庫中的阻塞隊列

3.1Java提供阻塞隊列實現(xiàn)的標準類

java官方也提供了阻塞隊列的標準類,主要有下面幾個:

標準類說明
ArrayBlockingQueue一個由數(shù)組結(jié)構(gòu)組成的有界阻塞隊列
LinkedBlockingQueue一個由鏈表結(jié)構(gòu)組成的有界阻塞隊列
PriorityBlockingQueue一個支持優(yōu)先級排序的無界阻塞隊列
DelayQueue一個使用優(yōu)先級隊列實現(xiàn)的無界阻塞隊列
SynchronousQueue一個不存儲元素的阻塞隊列
LinkedTransferQueue一個由鏈表結(jié)構(gòu)組成的無界阻塞隊列
LinkedBlockingDeque一個由鏈表結(jié)構(gòu)組成的雙向阻塞隊列
BlockingQueue接口單向阻塞隊列實現(xiàn)了該接口
BlockingDeque接口雙向阻塞隊列實現(xiàn)了該接口

3.2Blockingqueue基本使用

在 Java 標準庫中內(nèi)置了阻塞隊列. 如果我們需要在一些程序中使用阻塞隊列, 直接使用標準庫中的即可.

BlockingQueue 是一個接口. 真正實現(xiàn)的類是 LinkedBlockingQueue.

put 方法用于阻塞式的入隊列, take 用于阻塞式的出隊列.

BlockingQueue 也有 offer, poll, peek 等方法, 但是這些方法不帶有阻塞特性.

BlockingQueue<String> queue = new LinkedBlockingQueue<>();
// 入隊列
queue.put("abc");
// 出隊列. 如果沒有 put 直接 take, 就會阻塞.
String elem = queue.take();

四.阻塞隊列實現(xiàn)

4.1阻塞隊列的代碼實現(xiàn)

我們通過 “循環(huán)隊列” 的方式來實現(xiàn)

使用 synchronized 進行加鎖控制.put 插入元素的時候, 判定如果隊列滿了, 就進行 wait. (注意, 要在循環(huán)中進行 wait. 被喚醒時不一定隊列就不滿了, 因為同時可能是喚醒了多個線程).take 取出元素的時候, 判定如果隊列為空, 就進行 wait. (也是循環(huán) wait)

我們在設(shè)計阻塞隊列的時候可以將隊列聯(lián)想成一個圓

class BlockingQueue{
    //隊列里存放的個數(shù)
   volatile private int size = 0;
    //隊列的頭節(jié)點
    private int head = 0;
    //隊列的尾節(jié)點
    private int prov = 0;
    //創(chuàng)建一個數(shù)組,我們來給這個數(shù)組的容量設(shè)置為100
    private int[] array = new int[100];
    //創(chuàng)建一個專業(yè)的鎖對象
    private Object object = new Object();
    //實現(xiàn)阻塞隊列中的put方法
    public void put(int value) throws InterruptedException {
        synchronized (object) {
            //當數(shù)組已經(jīng)滿了
            if (size == array.length) {
                object.wait();
            } else {
                //我們可以優(yōu)化成prov = (prov + 1) % items.length
                array[prov] = value;
                prov ++;
               if (prov >= array.length) {
                   prov = 0;
               }
            }
            size++;
            object.notify();
        }
    }
    //實現(xiàn)阻塞隊列中的take方法
    public int take() throws InterruptedException {
        synchronized (object) {
            if (size == 0) {
                object.wait();
            }
            int x = array[head];
            head++;
            if (head >= array.length) {
                head = 0;
            }
            size--;
            object.notify();
            return x;
        }
    }
}

4.2阻塞隊列搭配生產(chǎn)者與消費者的代碼實現(xiàn)

class BlockingQueue{
    //隊列里存放的個數(shù)
   volatile private int size = 0;
    //隊列的頭節(jié)點
    private int head = 0;
    //隊列的尾節(jié)點
    private int prov = 0;
    //創(chuàng)建一個數(shù)組,我們來給這個數(shù)組的容量設(shè)置為100
    private int[] array = new int[100];
    //創(chuàng)建一個專業(yè)的鎖對象
    private Object object = new Object();
    //實現(xiàn)阻塞隊列中的put方法
    public void put(int value) throws InterruptedException {
        synchronized (object) {
            //當數(shù)組已經(jīng)滿了
            if (size == array.length) {
                object.wait();
            } else {
                //我們可以優(yōu)化成prov = (prov + 1) % items.length
                array[prov] = value;
                prov ++;
               if (prov >= array.length) {
                   prov = 0;
               }
            }
            size++;
            object.notify();
        }
    }
    //實現(xiàn)阻塞隊列中的take方法
    public int take() throws InterruptedException {
        synchronized (object) {
            if (size == 0) {
                object.wait();
            }
            int x = array[head];
            head++;
            if (head >= array.length) {
                head = 0;
            }
            size--;
            object.notify();
            return x;
        }
    }
}
public class Test {
    public static void main(String[] args) {
        BlockingQueue blockingQueue = new BlockingQueue();
        Thread thread1 = new Thread(()-> {
            while (true) {
                for (int i = 0; i < 100; i++) {
                    try {
                        blockingQueue.put(i);
                        System.out.println("生產(chǎn)了"+i);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        Thread thread2 = new Thread(()->{
                while (true) {
                    try {
                        int b = blockingQueue.take();
                        System.out.println("消耗了"+b);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
        });
        thread1.start();
        thread2.start();
    }
}

以上就是Java多線程案例之阻塞隊列詳解的詳細內(nèi)容,更多關(guān)于Java多線程阻塞隊列的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java 8新時間日期庫java.time的使用示例

    Java 8新時間日期庫java.time的使用示例

    這篇文章主要給你大家介紹了關(guān)于Java 8新時間日期庫java.time的使用示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2020-07-07
  • IDEA 程序包不存在,找不到符號但是明明存在對應的jar包(問題分析及解決方案)

    IDEA 程序包不存在,找不到符號但是明明存在對應的jar包(問題分析及解決方案)

    這篇文章主要介紹了IDEA 程序包不存在,找不到符號但是明明存在對應的jar包 的解決方案,本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-08-08
  • Java實現(xiàn)終止線程池中正在運行的定時任務(wù)

    Java實現(xiàn)終止線程池中正在運行的定時任務(wù)

    本篇文章給大家分享了JAVA中實現(xiàn)終止線程池中正在運行的定時任務(wù)的具體步驟和方法,有需要的朋友跟著學習下。
    2018-05-05
  • Java實題演練二叉搜索樹與雙向鏈表分析

    Java實題演練二叉搜索樹與雙向鏈表分析

    這篇文章主要介紹了Java二叉搜索樹與雙向鏈表,總的來說這并不是一道難題,那為什么要拿出這道題介紹?拿出這道題真正想要傳達的是解題的思路,以及不斷優(yōu)化探尋最優(yōu)解的過程。希望通過這道題能給你帶來一種解題優(yōu)化的思路
    2022-12-12
  • 如何用Netty實現(xiàn)高效的HTTP服務(wù)器

    如何用Netty實現(xiàn)高效的HTTP服務(wù)器

    這篇文章主要介紹了如何用Netty實現(xiàn)高效的HTTP服務(wù)器,對HTTP感興趣的同學可以參考一下
    2021-04-04
  • spring jdbctemplate的用法小結(jié)

    spring jdbctemplate的用法小結(jié)

    jdbcTemplate是spring框架中提供的一個對象,是對原始繁雜的jdbc 對象的簡單封裝,本文通過實例代碼介紹spring jdbctemplate的用法小結(jié),需要的朋友可以參考下
    2023-04-04
  • Java中notify和notifyAll的區(qū)別及何時使用

    Java中notify和notifyAll的區(qū)別及何時使用

    本文主要介紹了Java中notify和notifyAll的區(qū)別及何時使用,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 解決Spring Boot中Druid連接池“discard long time none received connection“警告

    解決Spring Boot中Druid連接池“discard long time 

    本文主要介紹了解決Spring Boot中Druid連接池“discard long time none received connection“警告,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-03-03
  • Java生成驗證碼功能實例代碼

    Java生成驗證碼功能實例代碼

    頁面上輸入驗證碼是比較常見的一個功能,實現(xiàn)起來也很簡單.給大家寫一個簡單的生成驗證碼的示例程序,需要的朋友可以借鑒一下
    2017-05-05
  • Java分批將List數(shù)據(jù)導入數(shù)據(jù)庫的解決過程

    Java分批將List數(shù)據(jù)導入數(shù)據(jù)庫的解決過程

    這篇文章主要給大家介紹了關(guān)于Java分批將List數(shù)據(jù)導入數(shù)據(jù)庫的解決過程,文中通過代碼示例介紹的非常詳細,對大家學習或者使用java具有一定的參考學習價值,需要的朋友可以參考下
    2023-08-08

最新評論

年辖:市辖区| 平湖市| 宝丰县| 宁津县| 昌乐县| 金昌市| 灌云县| 陆丰市| 沙河市| 南和县| 巴彦淖尔市| 格尔木市| 剑阁县| 独山县| 八宿县| 富平县| 柳江县| 固原市| 永仁县| 韶关市| 南郑县| 罗甸县| 宝丰县| 天镇县| 望都县| 开远市| 景德镇市| 买车| 龙里县| 赤城县| 闽侯县| 连南| 麦盖提县| 榆中县| 霍山县| 那坡县| 朔州市| 五家渠市| 嘉义县| 中超| 东台市|