Java的java.util.concurrent.*包下有許多在併發場景下使用的集合,ArrayBlockingQueue是其中之一,它是一個循環隊列,這個隊列的特別之處在於take方法與put方法,分別對應隊列的元素出列和元素入列操作,當隊列爲空時,take會使得線程進入等待狀態,直到隊列不爲空,有元素能夠出列纔會繼續執行;同理,當隊列滿時,put方法也會使得線程進入等待狀態。
實際上這是一個生產者-消費者模型,按照理解, 自己也試着實現了一個,代碼如下
/** * Created by YotWei on 2018/7/1. */ public class BlockingQueue<E> { /** * 有界隊列內部固定長度,因此可以用數組實現 */ private Object[] elements; /** * 隊列的頭和尾下標 */ private int head = 0, tail = 0; /** * 隊列目前的長度 */ private int size; private ReentrantLock lock = new ReentrantLock(); private Condition notEmpty = lock.newCondition(); private Condition notFull = lock.newCondition(); public BlockingQueue(int capacity) { this.elements = new Object[capacity]; } public void put(E e) { lock.lock(); try { while (size == elements.length) notFull.await(); elements[tail] = e; if (++tail == elements.length) { tail = 0; } size++; notEmpty.signal(); } catch (InterruptedException ex) { ex.printStackTrace(); } finally { lock.unlock(); } } public E take() { lock.lock(); E e = null; try { while (size == 0) { notEmpty.await(); } e = (E) elements[head]; elements[head] = null; if (++head == elements.length) head = 0; size--; notFull.signal(); } catch (InterruptedException ex) { ex.printStackTrace(); } finally { lock.unlock(); } return e; } public int size() { lock.lock(); try { return size; } finally { lock.unlock(); } } }
實際上ArrayBlockingQueue還包含許多其它方法,這兩個是最核心的。