首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Java 非阻塞線程安全雙端佇列 ConcurrentLinkedDeque 完整實戰指南

     編輯:關於C++

Java ConcurrentLinkedDeque 完整實戰指南

ConcurrentLinkedDeque 是 Java 7 引入的非阻塞線程安全雙端佇列,基於 CAS(Compare-And-Swap)無鎖演算法實現,適合高併發場景下多執行緒共享存取集合。

核心特性

  • 非阻塞:操作無法立即完成時拋出異常或回傳 null,不阻塞執行緒
  • 線程安全:多執行緒同時增刪不會導致資料不一致
  • 雙端操作:支援頭尾兩端的插入、移除、查看操作
  • 弱一致性迭代器:反映建立迭代器時刻的狀態,不拋出 ConcurrentModificationException
  • 不允許 null 元素:嘗試插入 null 會拋出 NullPointerException

核心 API 分類

操作類型方法行為
插入add(e) / addLast(e)尾端插入,成功回傳 true
addFirst(e)頭端插入
移除並回傳pollFirst() / pollLast()空佇列回傳 null
removeFirst() / removeLast()空佇列拋出 NoSuchElementException
pop()等同 removeFirst()
查看不移除peekFirst() / peekLast()空佇列回傳 null
getFirst() / getLast()空佇列拋出 NoSuchElementException
peek()等同 peekFirst()

實戰範例:生產者-消費者模型

import java.util.concurrent.ConcurrentLinkedDeque;

public class AddTask implements Runnable {
    private final ConcurrentLinkedDeque deque;
    
    public AddTask(ConcurrentLinkedDeque deque) {
        this.deque = deque;
    }
    
    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        for (int i = 0; i < 10000; i++) {
            deque.add(name + ": Element " + i); // 尾端插入
        }
    }
}

public class RemoveTask implements Runnable {
    private final ConcurrentLinkedDeque deque;
    
    public RemoveTask(ConcurrentLinkedDeque deque) {
        this.deque = deque;
    }
    
    @Override
    public void run() {
        for (int i = 0; i < 5000; i++) {
            deque.pollFirst(); // 頭端移除
            deque.pollLast();  // 尾端移除
        }
    }
}

public class Main {
    public static void main(String[] args) throws InterruptedException {
        ConcurrentLinkedDeque deque = new ConcurrentLinkedDeque<>();
        Thread[] threads = new Thread[100];
        
        // 啟動 100 個生產者執行緒
        for (int i = 0; i < 100; i++) {
            threads[i] = new Thread(new AddTask(deque));
            threads[i].start();
        }
        System.out.printf("Main: %d AddTask threads launched\n", threads.length);
        
        // 等待所有生產者完成
        for (Thread t : threads) t.join();
        System.out.printf("Main: Deque size after add: %d\n", deque.size()); // 1,000,000
        
        // 啟動 100 個消費者執行緒
        for (int i = 0; i < 100; i++) {
            threads[i] = new Thread(new RemoveTask(deque));
            threads[i].start();
        }
        System.out.printf("Main: %d RemoveTask threads launched\n", threads.length);
        
        for (Thread t : threads) t.join();
        System.out.printf("Main: Deque size after remove: %d\n", deque.size()); // 0
    }
}

輸出結果

Main: 100 AddTask threads launched
Main: Deque size after add: 1000000
Main: 100 RemoveTask threads launched
Main: Deque size after remove: 0

使用注意事項

  • size() 非精確:遍歷計數過程中佇列可能被修改,僅在無執行緒修改時可信
  • 適合場景:多執行緒共享存取、非阻塞需求、雙端操作需求
  • 替代方案:若需阻塞特性,考慮 LinkedBlockingDeque;單端佇列用 ConcurrentLinkedQueue
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved