並發編程ConcurrentLinkedQueue示例詳解

ConcurrentLinkedQueue

ConcurrentLinkedQueue是非阻塞線程安全的隊列,適用於高並發的場景。是一個基於鏈接節點的無界線程安全隊列,按照 FIFO(先進先出)原則對元素進行排序。隊列元素中不可以放置null元素(內部實現的特殊節點除外)

ConcurrentLinkedQueue原理

  • ConcurrentLinked是由鏈表結構組成的線程安全的先進先出無界隊列。
  • 當多線程要共享訪問集合時,ConcurrentLinkedQueue是一個比較好的選擇。
  • 不允許插入null元素
  • 支持非阻塞地訪問並發安全的隊列,不會拋出ConcurrentModifiationException異常。
  • size方法不是準確的,因為在統計集合的時候,隊列可能正在添加元素,導致統計不準。
  • 批量操作addAll、removeAll、retainAll、containsAll、equals和toArray不保證原子性(操作不可分割)
  • 添加元素happen-before其他線程移除元素。

ConcurrentLinkedQueue類繼承AbstractQueue抽象類

具有隊列的功能;實現瞭Queue接口,可作為隊列使用。

  • ConcurrentLinkedQueue繼承於AbstractQueue。
  • ConcurrentLinkedQueue內部是通過鏈表來實現的。同時包含鏈表的頭節點head和尾節點tail。
  • ConcurrentLinkedQueue按照 FIFO(先進先出)原則對元素進行排序。元素都是從尾部插入到鏈表,從頭部開始返回。
  • ConcurrentLinkedQueue的鏈表Node中的next的類型是volatile,而且鏈表數據item的類型也是volatile。ConcurrentLinkedQueue就是通過volatile來實現多線程對競爭資源的互斥訪問的。
  • 其中head節點存放鏈表第一個item為null的節點,tail則並不是總指向最後一個節點

ConcurrentLinkedQueue操作方法

private transient volatile Node<E> head;
private transient volatile Node<E> tail;
public ConcurrentLinkedQueue() {
    head = tail = new Node<E>(null);
}

構造函數中,新建瞭一個“內容為null的節點”,並設置表頭head和表尾tail的值為新節點。 head和tail是volatile類型,具有volatile賦予的含義:“即對一個volatile變量的讀,總是能看到(任意線程)對這個volatile變量最後的寫入”。

private static class Node<E> {
    volatile E item;
    volatile Node<E> next;
    Node(E item) {
        UNSAFE.putObject(this, itemOffset, item);
    }
}

Node是單向鏈表節點,next指向下一個Node,item用於存儲數據。Node中操作節點數據的API,是通過Unsafe機制的CAS函數實現的;例如casNext()是通過CAS函數“比較並設置節點的下一個節點”。

1、添加

  以add(E e)為例對ConcurrentLinkedQueue中的添加

public boolean add(E e) {
  return offer(e);
}

add()實際上是調用的offer()來完成添加操作的;offer(E e)的作用就是將元素e添加到鏈表的末尾。

2、刪除

poll():在鏈表頭部獲取並且移除一個元素

poll()的作用就是刪除鏈表的表頭節點,並返回被刪節點對應的值。

3、peek操作

peek操作是獲取鏈表頭部一個元素(隻讀取不移除)。

以上就是並發編程ConcurrentLinkedQueue示例詳解的詳細內容,更多關於並發編程ConcurrentLinkedQueue的資料請關註WalkonNet其它相關文章!

推薦閱讀: