欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java中阻塞隊列和非阻塞隊列的實現(xiàn)

 更新時間:2024年10月13日 09:35:24   作者:Flying_Fish_Xuan  
在Java并發(fā)編程中,阻塞隊列和非阻塞隊列是兩種主要的隊列類型,分別適用于不同的場景,了解這兩種隊列的特點和工作機制,可以幫助開發(fā)者更好地選擇合適的數(shù)據(jù)結(jié)構(gòu)解決并發(fā)問題

在 Java 中,**阻塞隊列(Blocking Queue)非阻塞隊列(Non-Blocking Queue)**是兩種用于并發(fā)編程的隊列類型,它們在多線程環(huán)境中有不同的行為和用途。它們的主要區(qū)別在于對操作的處理方式:阻塞隊列在操作無法立即完成時會阻塞線程,而非阻塞隊列則立即返回或進(jìn)行其他操作。

1. 什么是阻塞隊列?

阻塞隊列(Blocking Queue)是一種線程安全的隊列,它在 Java 中位于 java.util.concurrent 包中。阻塞隊列支持在隊列為空時自動等待(即阻塞)直到有元素可以消費,或者在隊列已滿時自動等待直到有空間可以插入新元素。這種行為使得阻塞隊列在生產(chǎn)者-消費者模型中非常有用。

阻塞隊列的操作包括阻塞的插入操作阻塞的刪除操作。它們的主要方法有:

  • put(E e):如果隊列已滿,當(dāng)前線程將被阻塞,直到隊列有可用空間。
  • take():如果隊列為空,當(dāng)前線程將被阻塞,直到隊列中有可用元素。

Java 中常用的阻塞隊列有以下幾種:

  • ArrayBlockingQueue:一個有界的阻塞隊列,基于數(shù)組實現(xiàn)。固定大小,支持公平性設(shè)置。

  • LinkedBlockingQueue:一個可選有界的阻塞隊列,基于鏈表實現(xiàn)。默認(rèn)大小為 Integer.MAX_VALUE,適用于任務(wù)生產(chǎn)和消費速率不同的場景。

  • PriorityBlockingQueue:一個支持優(yōu)先級排序的無界阻塞隊列,基于堆實現(xiàn),元素按優(yōu)先級順序出隊。

  • DelayQueue:一個支持延遲獲取元素的無界阻塞隊列,只有在元素的延遲期滿后才能從隊列中獲取元素。

  • SynchronousQueue:一個不存儲元素的阻塞隊列,每個插入操作必須等待一個相應(yīng)的刪除操作。適用于交換場景。

2. 什么是非阻塞隊列?

非阻塞隊列(Non-Blocking Queue)是一種不進(jìn)行阻塞的線程安全隊列。非阻塞隊列不等待當(dāng)前線程完成操作,而是立即返回或執(zhí)行其他操作。它們通常使用 CAS(Compare-And-Swap) 操作來確保線程安全性,從而避免線程在等待鎖時發(fā)生阻塞。

非阻塞隊列的操作包括非阻塞的插入操作非阻塞的刪除操作。它們的主要方法有:

  • offer(E e):嘗試插入元素到隊列中,如果成功則返回 true,如果隊列已滿則立即返回 false
  • poll():嘗試從隊列中取出一個元素,如果成功則返回元素,如果隊列為空則立即返回 null。

Java 中常用的非阻塞隊列有:

  • ConcurrentLinkedQueue:一個基于鏈表的無界非阻塞隊列,使用 CAS 操作來實現(xiàn)線程安全。適用于高并發(fā)場景。

  • ConcurrentLinkedDeque:一個雙端非阻塞隊列,基于鏈表實現(xiàn),支持在隊列的兩端進(jìn)行插入和刪除操作。

3. 阻塞隊列和非阻塞隊列的區(qū)別

  • 阻塞與非阻塞:阻塞隊列在讀取或?qū)懭霑r可能會發(fā)生阻塞,而普通隊列則不會發(fā)生這種情況。當(dāng)一個線程嘗試從空的普通隊列中讀取數(shù)據(jù)或向已滿的普通隊列中寫入數(shù)據(jù)時,它將直接返回一個特定的值,而不是等待其他線程的操作。

  • 同步與異步:阻塞隊列通常用于同步處理場景,而普通隊列通常用于異步處理場景。在同步處理場景下,多個線程之間需要協(xié)調(diào)工作,而在異步處理場景下,多個線程之間可以獨立地進(jìn)行各自的任務(wù)

  • 性能差異:由于阻塞隊列使用了鎖機制,所以在高并發(fā)情況下可能會出現(xiàn)性能瓶頸;而非阻塞隊列使用了原子操作和CAS指令,因此在高并發(fā)情況下具有更好的性能表現(xiàn)。

4. 使用場景和選擇指南

阻塞隊列和非阻塞隊列各自適用于不同的場景。了解它們的特點和工作機制可以幫助開發(fā)者更好地選擇合適的數(shù)據(jù)結(jié)構(gòu)來解決并發(fā)問題。

4.1 阻塞隊列的使用場景

  • 生產(chǎn)者-消費者模型:阻塞隊列最常見的應(yīng)用場景就是生產(chǎn)者-消費者模型。在這種模型中,生產(chǎn)者線程不斷地將任務(wù)放入隊列,消費者線程不斷地從隊列中取任務(wù)。使用阻塞隊列可以避免生產(chǎn)者或消費者線程在隊列為空或已滿時的忙等待,從而提高系統(tǒng)性能。

  • 任務(wù)調(diào)度和工作線程池:在任務(wù)調(diào)度系統(tǒng)或工作線程池中,阻塞隊列可以用于存放任務(wù)。線程池的工作線程可以從隊列中取任務(wù)并執(zhí)行,如果沒有任務(wù)則自動等待直到有新任務(wù)到來。

  • 延遲任務(wù)執(zhí)行DelayQueue 適用于需要在一定延遲后執(zhí)行任務(wù)的場景,例如定時任務(wù)調(diào)度。

4.2 非阻塞隊列的使用場景

  • 高并發(fā)場景:非阻塞隊列通常用于需要高并發(fā)訪問的場景,因為它不使用鎖而是依賴 CAS 操作來確保線程安全,從而減少了鎖競爭的開銷,能夠提供更高的吞吐量。

  • 低延遲應(yīng)用:對于需要快速響應(yīng)、低延遲的應(yīng)用,非阻塞隊列是非常適合的選擇。例如,在金融交易系統(tǒng)或高性能計算系統(tǒng)中,需要非??焖俚靥幚碚埱蠖皇苕i的影響。

  • 無界隊列:非阻塞隊列通常是無界的,例如 ConcurrentLinkedQueue,這意味著它們不會限制隊列大小,但要小心使用,避免內(nèi)存溢出。

5. 阻塞隊列和非阻塞隊列的實現(xiàn)原理

5.1 阻塞隊列的實現(xiàn)原理

阻塞隊列的實現(xiàn)依賴于內(nèi)部鎖和條件變量(Condition)來實現(xiàn)線程同步。例如,ArrayBlockingQueue 的實現(xiàn)如下:

  • 插入操作put():如果隊列已滿,插入線程會被放入“等待可用空間”的條件隊列中,直到有其他線程取走元素并喚醒它。
  • 取出操作(take():如果隊列為空,取出線程會被放入“等待元素”的條件隊列中,直到有其他線程插入元素并喚醒它。

這些方法通過 ReentrantLock 和 Condition 來實現(xiàn)同步控制:

public void put(E e) throws InterruptedException {
    final ReentrantLock lock = this.lock;
    lock.lockInterruptibly();
    try {
        while (count == items.length)
            notFull.await();  // 等待隊列非滿
        enqueue(e);
    } finally {
        lock.unlock();
    }
}

5.2 非阻塞隊列的實現(xiàn)原理

非阻塞隊列通常使用 CAS(Compare-And-Swap)操作來實現(xiàn)線程安全。ConcurrentLinkedQueue 是一個典型的非阻塞隊列,它通過鏈表的方式實現(xiàn)。其 offer() 和 poll() 方法實現(xiàn)如下:

  • 插入操作(offer():使用 CAS 操作來將新節(jié)點插入到鏈表的末尾。如果失敗則不斷重試,直到成功為止。

  • 取出操作(poll():使用 CAS 操作來獲取并移除鏈表的頭節(jié)點,同樣會在操作失敗時進(jìn)行重試,直到成功。

public boolean offer(E e) {
    final Node<E> newNode = new Node<>(e);
    for (Node<E> t = tail, p = t;;) {
        Node<E> q = p.next;
        if (q

 == null) {
            if (p.casNext(null, newNode)) {
                if (p != t)
                    casTail(t, newNode);  // 使用 CAS 更新尾節(jié)點
                return true;
            }
        } else if (p == q)
            p = (t != (t = tail)) ? t : head;
        else
            p = (p != t && t != (t = tail)) ? t : q;
    }
}

6. 示例代碼

下面是一個使用阻塞隊列和非阻塞隊列的簡單示例:

阻塞隊列示例:ArrayBlockingQueue

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

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

        // 生產(chǎn)者線程
        Thread producer = new Thread(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    System.out.println("生產(chǎn)者生產(chǎn): " + i);
                    queue.put(i);  // 阻塞插入操作
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

        // 消費者線程
        Thread consumer = new Thread(() -> {
            try {
                while (true) {
                    Integer item = queue.take();  // 阻塞取出操作
                    System.out.println("消費者消費: " + item);
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
        });

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

非阻塞隊列示例:ConcurrentLinkedQueue

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

public class NonBlockingQueueExample {
    public static void main(String[] args) {
        Queue<Integer> queue = new ConcurrentLinkedQueue<>();

        // 添加元素
        queue.offer(1);
        queue.offer(2);
        queue.offer(3);

        // 取出元素
        Integer item;
        while ((item = queue.poll()) != null) {
            System.out.println("取出: " + item);
        }
    }
}

7. 總結(jié)

阻塞隊列和非阻塞隊列在 Java 并發(fā)編程中具有不同的應(yīng)用場景和特點。阻塞隊列通過內(nèi)部鎖和條件變量實現(xiàn)線程安全,適用于生產(chǎn)者-消費者模型和任務(wù)調(diào)度等場景。非阻塞隊列通過 CAS 操作實現(xiàn)線程安全,適用于高并發(fā)和低延遲場景。

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

相關(guān)文章

  • SpringBoot集成Shiro進(jìn)行權(quán)限控制和管理的示例

    SpringBoot集成Shiro進(jìn)行權(quán)限控制和管理的示例

    這篇文章主要介紹了SpringBoot集成Shiro進(jìn)行權(quán)限控制和管理的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • java實現(xiàn)多線程交替打印

    java實現(xiàn)多線程交替打印

    這篇文章主要為大家詳細(xì)介紹了java實現(xiàn)多線程交替打印,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • java轉(zhuǎn)換字符串編碼格式的方法

    java轉(zhuǎn)換字符串編碼格式的方法

    這篇文章主要介紹了java轉(zhuǎn)換字符串編碼格式的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-08-08
  • 全解史上最快的JOSN解析庫alibaba Fastjson

    全解史上最快的JOSN解析庫alibaba Fastjson

    這篇文章主要介紹了史上最快的JOSN解析庫alibaba Fastjson,對FastJson感興趣的同學(xué),一定要看一下
    2021-04-04
  • java web返回中文亂碼問題及解決

    java web返回中文亂碼問題及解決

    這篇文章主要介紹了java web返回中文亂碼問題及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-05-05
  • Spring Native項目實戰(zhàn)(體驗79毫秒啟動springboot應(yīng)用)

    Spring Native項目實戰(zhàn)(體驗79毫秒啟動springboot應(yīng)用)

    Spring Native是Spring提供的、制作native image的技術(shù)方案,本篇主要內(nèi)容是開發(fā)springboot應(yīng)用再構(gòu)建為native image的方法,通過Spring Native項目實戰(zhàn)讓大家體驗79毫秒啟動springboot應(yīng)用,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • Spring注解 TX聲明式事務(wù)實現(xiàn)過程解析

    Spring注解 TX聲明式事務(wù)實現(xiàn)過程解析

    這篇文章主要介紹了Spring注解 - TX 聲明式事務(wù)實現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-04-04
  • java合并多個文件的兩種方法

    java合并多個文件的兩種方法

    這篇文章主要為大家詳細(xì)介紹了java合并多個文件的兩種方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • SpringBoot如何訪問本地圖片

    SpringBoot如何訪問本地圖片

    這篇文章主要介紹了SpringBoot如何訪問本地圖片問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Java之JSF框架案例詳解

    Java之JSF框架案例詳解

    這篇文章主要介紹了Java之JSF框架案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下
    2021-09-09

最新評論