天天看點

(十三)J.U.C-BlockingQueue

BlockingQueue阻塞隊列

主要應用場景:生産者消費者模型,是線程安全的

(十三)J.U.C-BlockingQueue

阻塞情況:

1、當隊列滿了進行入隊操作

2、當隊列空了的時候進行出隊列操作

四套方法:

BlockingQueue提供了四套方法,分别來進行插入、移除、檢查。每套方法在不能立刻執行時都有不同的反應。

(十三)J.U.C-BlockingQueue
  • Throws Exceptions :如果不能立即執行就抛出異常。
  • Special Value:如果不能立即執行就傳回一個特殊的值。
  • Blocks:如果不能立即執行就阻塞
  • Times Out:如果不能立即執行就阻塞一段時間,如果過了設定時間還沒有被執行,則傳回一個值

實作類:

  • ArrayBlockingQueue:它是一個有界的阻塞隊列,内部實作是數組,初始化時指定容量大小,一旦指定大小就不能再變。采用FIFO方式存儲元素。
  • DelayQueue:阻塞内部元素,内部元素必須實作Delayed接口,Delayed接口又繼承了Comparable接口,原因在于DelayQueue内部元素需要排序,一般情況按過期時間優先級排序。
public interface Delayed extends Comparable<Delayed> {
    long getDelay(TimeUnit unit);
}
           

DalayQueue内部采用PriorityQueue與ReentrantLock實作。

public class DelayQueue<E extends Delayed> extends AbstractQueue<E>
    implements BlockingQueue<E> {

    private final transient ReentrantLock lock = new ReentrantLock();
    private final PriorityQueue<E> q = new PriorityQueue<E>();
    ...
}
           
  • LinkedBlockingQueue:大小配置可選,如果初始化時指定了大小,那麼它就是有邊界的。不指定就無邊界(最大整型值)。内部實作是連結清單,采用FIFO形式儲存資料。
public LinkedBlockingQueue() {
    this(Integer.MAX_VALUE);//不指定大小,無邊界采用預設值,最大整型值
}
           
  • PriorityBlockingQueue:帶優先級的阻塞隊列。無邊界隊列,允許插入null。插入的對象必須實作Comparator接口,隊列優先級的排序規則就是按照我們對Comparable接口的實作來指定的。我們可以從PriorityBlockingQueue中擷取一個疊代器,但這個疊代器并不保證能按照優先級的順序進行疊代。
public boolean add(E e) {//添加方法
    return offer(e);
}
public boolean offer(E e) {
    if (e == null)
        throw new NullPointerException();
    final ReentrantLock lock = this.lock;
    lock.lock();
    int n, cap;
    Object[] array;
    while ((n = size) >= (cap = (array = queue).length))
        tryGrow(array, cap);
    try {
        Comparator<? super E> cmp = comparator;//必須實作Comparator接口
        if (cmp == null)
            siftUpComparable(n, e, array);
        else
            siftUpUsingComparator(n, e, array, cmp);
        size = n + 1;
        notEmpty.signal();
    } finally {
        lock.unlock();
    }
    return true;
}
           
  • SynchronusQueue:隻能插入一個元素,同步隊列,無界非緩存隊列,不存儲元素。

作為BlockingQueue中的一員,SynchronousQueue與其他BlockingQueue有着不同特性:

  1. SynchronousQueue沒有容量。與其他BlockingQueue不同,SynchronousQueue是一個不存儲元素的BlockingQueue。每一個put操作必須要等待一個take操作,否則不能繼續添加元素,反之亦然。
  2. 因為沒有容量,是以對應 peek, contains, clear, isEmpty … 等方法其實是無效的。例如clear是不執行任何操作的,contains始終傳回false,peek始終傳回null。
  3. SynchronousQueue分為公平和非公平,預設情況下采用非公平性通路政策,當然也可以通過構造函數來設定為公平性通路政策(為true即可)。
  4. 若使用 TransferQueue, 則隊列中永遠會存在一個 dummy node(這點後面詳細闡述)。

SynchronousQueue非常适合做交換工作,生産者的線程和消費者的線程同步以傳遞某些資訊、事件或者任務。

繼續閱讀