概要:
ArrayBlockingQueue的内部是通过一个可重入锁ReentrantLock和两个Condition条件对象来实现阻塞
注意这两个Condition即ReentrantLock的Condition:ReentrantLock的内部类Sync继承了AQS这个抽象类,Sync的newCondition()返回AQS的ConditionObject
关键:队列已经满时入队,将当前线程加入notFull这个Condition等待队列,唤醒等待notEmpty条件的线程。
关键:队列为空时出队,将当前线程加入notEmpty这个Condition等待队列,唤醒等待notFull条件的线程
AQS维护了一个同步队列
Condition是JUC的一个接口,AQS的ConditionObject实现了这个接口,维护了一个等待队列(等待signal信号的队列)
线程调用reentrantLock.lock()时,线程被加入到AQS同步队列中;
线程A调用condition.await()方法时,线程A从AQS同步队列中被移除,被加入到Condition等待队列,等待signal信号
线程B调用signal()方法,Condition等待队列中有一个节点A,把它取出来(A)加入到AQS同步队列中。这时候线程A并没有被唤醒(signal可以指定唤醒哪个condition)
只有发送singal信号的线程调用reentrantLock.unLock()后,因为它(线程A)已经被加入到AQS同步队列并且成为同步队列头结点,所以线程才会被唤醒。
一、前言
在完成Map下的并发集合后,现在来分析ArrayBlockingQueue,ArrayBlockingQueue可以用作一个阻塞型队列,支持多任务并发操作,有了之前看源码的积累,再看ArrayBlockingQueue源码会很容易,下面开始正文。
ArrayBlockingQueue的内部是通过一个可重入锁ReentrantLock和两个Condition条件对象来实现阻塞
由于Java中的阻塞队列接口BlockingQueue继承自Queue接口,因此先来看看阻塞队列接口为我们提供的主要方法
public interface BlockingQueue<E> extends Queue<E> { //将指定的元素插入到此队列的尾部(如果立即可行且不会超过该队列的容量) //在成功时返回 true,如果此队列已满,则抛IllegalStateException。 boolean add(E e); //将指定的元素插入到此队列的尾部(如果立即可行且不会超过该队列的容量) // 将指定的元素插入此队列的尾部,如果该队列已满, //则在到达指定的等待时间之前等待可用的空间,该方法可中断 boolean offer(E e, long timeout, TimeUnit unit) throws InterruptedException; //将指定的元素插入此队列的尾部,如果该队列已满,则一直等到(阻塞)。 void put(E e) throws InterruptedException; //获取并移除此队列的头部,如果没有元素则等待(阻塞), //直到有元素将唤醒等待线程执行该操作 E take() throws InterruptedException; //获取并移除此队列的头部,在指定的等待时间前一直等到获取元素, //超过时间方法将结束 E poll(long timeout, TimeUnit unit) throws InterruptedException; //从此队列中移除指定元素的单个实例(如果存在)。 boolean remove(Object o); } //除了上述方法还有继承自Queue接口的方法 //获取但不移除此队列的头元素,没有则跑异常NoSuchElementException E element(); //获取但不移除此队列的头;如果此队列为空,则返回 null。 E peek(); //获取并移除此队列的头,如果此队列为空,则返回 null。 E poll();