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

java ArrayBlockingQueue阻塞隊列的實現(xiàn)示例

 更新時間:2024年02月21日 09:15:32   作者:一杯可樂、  
ArrayBlockingQueue是一個基于數(shù)組實現(xiàn)的阻塞隊列,本文就來介紹一下java ArrayBlockingQueue阻塞隊列的實現(xiàn)示例,具有一定的參考價值,感興趣的可以了解一下

在Java并發(fā)編程中,ArrayBlockingQueue是一個非常常用的工具類。它是一個由數(shù)組支持的有界阻塞隊列,提供了線程安全的隊列操作。

1.ArrayBlockingQueue概述

ArrayBlockingQueue是一個基于數(shù)組實現(xiàn)的阻塞隊列,它繼承自AbstractQueue并實現(xiàn)了BlockingQueue接口。這個隊列在創(chuàng)建時需要指定一個固定的大小,之后這個大小就不能再改變了。當(dāng)隊列滿時,如果再有新的元素試圖加入隊列,那么這個操作會被阻塞;同樣地,如果隊列為空,那么從隊列中取元素的操作也會被阻塞。這種特性使得ArrayBlockingQueue非常適合作為生產(chǎn)者-消費(fèi)者模式中的緩沖區(qū)。

2.ArrayBlockingQueue的核心特性

2.1.線程安全性

ArrayBlockingQueue是線程安全的,它通過內(nèi)部鎖機(jī)制保證了在多線程環(huán)境下的安全性。因此,在多線程環(huán)境中,你可以放心地使用它而不需要擔(dān)心數(shù)據(jù)的一致性問題。

2.2.阻塞控制

ArrayBlockingQueue提供了阻塞控制機(jī)制。當(dāng)隊列滿時,嘗試向隊列中添加元素的線程會被阻塞,直到隊列中有空間可用;同樣,當(dāng)隊列為空時,嘗試從隊列中取出元素的線程也會被阻塞,直到隊列中有元素可供消費(fèi)。這種機(jī)制可以有效地控制生產(chǎn)者和消費(fèi)者的速度,避免資源的浪費(fèi)。

2.3.有界性

ArrayBlockingQueue的有界性可以防止隊列無限制地增長,從而避免內(nèi)存溢出。在實際應(yīng)用中,這種有界性可以作為系統(tǒng)的一個流量控制閥,當(dāng)系統(tǒng)過載時,通過阻塞或拒絕請求來保護(hù)系統(tǒng)。

3.ArrayBlockingQueue的使用

3.1.創(chuàng)建ArrayBlockingQueue

創(chuàng)建一個ArrayBlockingQueue非常簡單,只需要指定隊列的大小即可:

int queueSize = 10;
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(queueSize);

3.2.生產(chǎn)者-消費(fèi)者模式

ArrayBlockingQueue常用于生產(chǎn)者-消費(fèi)者模式。生產(chǎn)者負(fù)責(zé)生成數(shù)據(jù)并添加到隊列中,而消費(fèi)者則從隊列中取出數(shù)據(jù)并處理。下面是一個簡單的生產(chǎn)者-消費(fèi)者示例:

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class ProducerConsumerExample {
    public static void main(String[] args) {
        BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(5);

        Thread producer = new Thread(() -> {
            for (int i = 0; i < 10; i++) {
                try {
                    System.out.println("生產(chǎn)者生產(chǎn)了數(shù)據(jù):" + i);
                    queue.put(i);
                    Thread.sleep(200);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        Thread consumer = new Thread(() -> {
            while (true) {
                try {
                    Integer data = queue.take();
                    System.out.println("消費(fèi)者消費(fèi)了數(shù)據(jù):" + data);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        producer.start();
        consumer.start();
    }
}

運(yùn)行結(jié)果:

生產(chǎn)者生產(chǎn)了數(shù)據(jù):0
消費(fèi)者消費(fèi)了數(shù)據(jù):0
生產(chǎn)者生產(chǎn)了數(shù)據(jù):1
消費(fèi)者消費(fèi)了數(shù)據(jù):1
生產(chǎn)者生產(chǎn)了數(shù)據(jù):2
消費(fèi)者消費(fèi)了數(shù)據(jù):2
生產(chǎn)者生產(chǎn)了數(shù)據(jù):3
消費(fèi)者消費(fèi)了數(shù)據(jù):3
生產(chǎn)者生產(chǎn)了數(shù)據(jù):4
消費(fèi)者消費(fèi)了數(shù)據(jù):4
生產(chǎn)者生產(chǎn)了數(shù)據(jù):5
消費(fèi)者消費(fèi)了數(shù)據(jù):5
生產(chǎn)者生產(chǎn)了數(shù)據(jù):6
消費(fèi)者消費(fèi)了數(shù)據(jù):6
生產(chǎn)者生產(chǎn)了數(shù)據(jù):7
消費(fèi)者消費(fèi)了數(shù)據(jù):7
生產(chǎn)者生產(chǎn)了數(shù)據(jù):8
消費(fèi)者消費(fèi)了數(shù)據(jù):8
生產(chǎn)者生產(chǎn)了數(shù)據(jù):9
消費(fèi)者消費(fèi)了數(shù)據(jù):9

在這個示例中,我們創(chuàng)建了一個大小為5的ArrayBlockingQueue,然后啟動了一個生產(chǎn)者線程和一個消費(fèi)者線程。生產(chǎn)者線程會生成10個數(shù)據(jù),并嘗試將它們添加到隊列中;消費(fèi)者線程則會不斷地從隊列中取出數(shù)據(jù)并處理。由于隊列的大小只有5,因此當(dāng)生產(chǎn)者生產(chǎn)了5個數(shù)據(jù)后,它會被阻塞,直到消費(fèi)者消費(fèi)了一些數(shù)據(jù)釋放出空間。同樣地,當(dāng)隊列為空時,消費(fèi)者線程也會被阻塞,直到生產(chǎn)者生產(chǎn)了新的數(shù)據(jù)。

4.ArrayBlockingQueue的最佳實踐

4.1.選擇合適的隊列大小

隊列的大小應(yīng)根據(jù)具體的應(yīng)用場景來設(shè)置。如果設(shè)置得太小,可能會導(dǎo)致頻繁的阻塞和上下文切換,影響性能;如果設(shè)置得太大,可能會浪費(fèi)內(nèi)存資源。因此,在選擇隊列大小時,需要綜合考慮系統(tǒng)的負(fù)載、內(nèi)存資源和性能要求等因素。

4.2.合理使用阻塞方法

ArrayBlockingQueue提供了多種阻塞方法,如puttake、offerpoll等。在使用這些方法時,需要根據(jù)具體的需求來選擇合適的方法。例如,如果你希望當(dāng)隊列滿時生產(chǎn)者線程能夠阻塞等待空間可用,那么可以使用put方法;如果你希望生產(chǎn)者線程在隊列滿時能夠立即返回并做其他處理,那么可以使用offer方法。

4.3.避免死鎖

在使用ArrayBlockingQueue時,需要注意避免死鎖的發(fā)生。例如,不要在持有其他鎖的情況下調(diào)用ArrayBlockingQueue的阻塞方法,否則可能會導(dǎo)致死鎖。此外,還需要注意避免循環(huán)等待和饑餓等問題。

4.4.考慮使用公平策略

ArrayBlockingQueue的構(gòu)造函數(shù)允許指定一個公平性參數(shù)。如果設(shè)置為true,等待時間最長的線程將優(yōu)先獲得訪問隊列的機(jī)會。但需要注意的是,公平性可能會降低性能。因此,在決定是否使用公平策略時,需要綜合考慮系統(tǒng)的性能和公平性要求。

5.源碼詳解

5.1.主要屬性

// 用于存儲隊列元素的數(shù)組
final Object[] items;

// 隊列的容量
int count;

// 控制并發(fā)訪問的鎖
final ReentrantLock lock;

// 隊列不滿時的等待條件
private final Condition notFull;

// 隊列不為空時的等待條件
private final Condition notEmpty;

// 隊列中等待取數(shù)據(jù)的線程數(shù)
final AtomicInteger waitingConsumers = new AtomicInteger();

// 隊列中等待插入數(shù)據(jù)的線程數(shù)
final AtomicInteger waitingProducers = new AtomicInteger();

5.2.構(gòu)造函數(shù)

ArrayBlockingQueue 提供了幾種構(gòu)造函數(shù),其中最基本的兩個是接受隊列容量和指定是否公平的構(gòu)造函數(shù)。

public ArrayBlockingQueue(int capacity) {
    this(capacity, false);
}

public ArrayBlockingQueue(int capacity, boolean fair) {
    if (capacity <= 0)
        throw new IllegalArgumentException();
    this.items = new Object[capacity];
    lock = new ReentrantLock(fair);
    notEmpty = lock.newCondition();
    notFull = lock.newCondition();
}

5.3.入隊操作

put(E e) 和 offer(E e) 是兩種入隊操作,其中 put 方法在隊列滿時會阻塞,而 offer 方法在隊列滿時會立即返回失敗或者根據(jù)提供的超時時間等待。

public void put(E e) throws InterruptedException {
    checkNotNull(e);
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == items.length)
            notFull.await();
        enqueue(e);
    } finally {
        lock.unlock();
    }
}

public boolean offer(E e, long timeout, TimeUnit unit)
    throws InterruptedException {

    checkNotNull(e);
    long nanos = unit.toNanos(timeout);
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == items.length) {
            if (nanos <= 0)
                return false;
            nanos = notFull.awaitNanos(nanos);
        }
        enqueue(e);
        return true;
    } finally {
        lock.unlock();
    }
}

private void enqueue(E x) {
    // 隊列尾部插入元素
    final Object[] items = this.items;
    items[putIndex] = x;
    if (++putIndex == items.length)
        putIndex = 0;
    count++;
    // 通知可能在等待的消費(fèi)者線程
    notEmpty.signal();
}

5.4.出隊操作

take() 和 poll() 是兩種出隊操作,其中 take 方法在隊列空時會阻塞,而 poll 方法在隊列空時會立即返回 null 或者根據(jù)提供的超時時間等待。

public E take() throws InterruptedException {
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == 0)
            notEmpty.await();
        return dequeue();
    } finally {
        lock.unlock();
    }
}

public E poll(long timeout, TimeUnit unit) throws InterruptedException {
    long nanos = unit.toNanos(timeout);
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == 0) {
            if (nanos <= 0)
                return null;
            nanos = notEmpty.awaitNanos(nanos);
        }
        return dequeue();
    } finally {
        lock.unlock();
    }
}

private E dequeue() {
    // 隊列頭部取出元素
    final Object[] items = this.items;
    @SuppressWarnings("unchecked")
    E x = (E) items[takeIndex];
    items[takeIndex] = null;
    if (++takeIndex == items.length)
        takeIndex = 0;
    count--;
    if (itrs != null)
        itrs.elementDequeued();
    // 通知可能在等待的生產(chǎn)者線程
    notFull.signal();
    return x;
}

6.總結(jié)

ArrayBlockingQueue是Java并發(fā)編程中一個非常實用的工具類。它提供了線程安全的阻塞隊列實現(xiàn),支持生產(chǎn)者-消費(fèi)者模式,并允許通過隊列的大小來控制系統(tǒng)的流量。在使用ArrayBlockingQueue時,需要注意選擇合適的隊列大小、合理使用阻塞方法、避免死鎖和考慮使用公平策略等問題。通過合理地使用ArrayBlockingQueue,可以有效地提高系統(tǒng)的并發(fā)性能和穩(wěn)定性。

到此這篇關(guān)于java ArrayBlockingQueue阻塞隊列的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)java ArrayBlockingQueue阻塞隊列內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java多線程通信:交替打印ABAB實例

    Java多線程通信:交替打印ABAB實例

    這篇文章主要介紹了Java多線程通信:交替打印ABAB實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-08-08
  • 基于Java快速實現(xiàn)一個簡單版的HashMap詳解

    基于Java快速實現(xiàn)一個簡單版的HashMap詳解

    這篇文章主要為大家詳細(xì)介紹了如何利用Java簡單實現(xiàn)一個底層數(shù)據(jù)結(jié)構(gòu)為數(shù)組?+?鏈表的HashMap,不考慮鏈表長度超過8個時變?yōu)榧t黑樹的情況,需要的可以參考一下
    2023-02-02
  • Java實現(xiàn)遞歸讀取文件夾下的所有文件

    Java實現(xiàn)遞歸讀取文件夾下的所有文件

    這篇文章主要為大家詳細(xì)介紹了如何利用Java實現(xiàn)遞歸讀取文件夾下的所有文件,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-02-02
  • java中的SpringBoot框架

    java中的SpringBoot框架

    這篇文章主要介紹了java學(xué)習(xí)之SpringBoot框架,文章基于Java的相關(guān)資料展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下
    2022-04-04
  • SpringBoot使用Spark過程詳解

    SpringBoot使用Spark過程詳解

    這篇文章主要介紹SpringBoot使用Spark的方法的相關(guān)知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強(qiáng),希望能幫助大家解決問題
    2023-02-02
  • Mybatis動態(tài)SQL之where標(biāo)簽用法說明

    Mybatis動態(tài)SQL之where標(biāo)簽用法說明

    這篇文章主要介紹了Mybatis動態(tài)SQL之where標(biāo)簽用法說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • JAVA基礎(chǔ)之注解與反射的使用方法和場景

    JAVA基礎(chǔ)之注解與反射的使用方法和場景

    這篇文章主要給大家介紹了關(guān)于JAVA基礎(chǔ)之注解與反射的使用方法和場景的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Springboot非分布式定時任務(wù)實現(xiàn)代碼

    Springboot非分布式定時任務(wù)實現(xiàn)代碼

    這篇文章主要介紹了Springboot非分布式定時任務(wù)實現(xiàn)代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-11-11
  • 關(guān)于Java8的foreach中使用return/break/continue產(chǎn)生的問題

    關(guān)于Java8的foreach中使用return/break/continue產(chǎn)生的問題

    這篇文章主要介紹了關(guān)于Java8的foreach()中使用return/break/continue產(chǎn)生的問題,在使用foreach()處理集合時不能使用break和continue這兩個方法,也就是說不能按照普通的for循環(huán)遍歷集合時那樣根據(jù)條件來中止遍歷,需要的朋友可以參考下
    2023-10-10
  • 詳解Java對象序列化為什么要使用SerialversionUID

    詳解Java對象序列化為什么要使用SerialversionUID

    這篇文章主要介紹了詳解Java對象序列化為什么要使用SerialversionUID,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11

最新評論

宁化县| 曲松县| 万山特区| 黄梅县| 乐至县| 策勒县| 佛坪县| 新干县| 上杭县| 昌平区| 贡山| 洪洞县| 德昌县| 秭归县| 松潘县| 马鞍山市| 镇宁| 津南区| 峨眉山市| 太白县| 布尔津县| 临汾市| 和静县| 夹江县| 柏乡县| 乐业县| 西贡区| 治县。| 渭南市| 蓝山县| 永宁县| 日喀则市| 阳新县| 桐庐县| 宁陕县| 重庆市| 光泽县| 丰镇市| 五寨县| 乌拉特中旗| 台南市|