JDK1.8源码泛读之ArrayBlockingQueue

线程池阻塞队列之:ArrayBlockingQueue

其内部以数组和ReentrantLock锁的方式实现的阻塞队列。


初始化队列长度,并且设置了基于同一个reentrantlock的条件Condition。

  • items内部数组,长度必须初始化
  • lock内部Reentrantlock对象
  • notEmpty:队列不是空的Condition
  • notFull:队列没有满Condition


添加队列元素

 1     public void put(E e) throws InterruptedException {
 2         checkNotNull(e);
 3         final ReentrantLock lock = this.lock;
 4         //同步锁开启
 5         lock.lockInterruptibly();
 6         try {
 7             //如果队列已经满了,进行已满条件阻塞,直到有人取出元素,导致notFull.signal
 8             while (count == items.length)
 9                 notFull.await();
10             //添加到队列
11             enqueue(e);
12         } finally {
13             lock.unlock();
14         }
15     }
16 
17     private void enqueue(E x) {
18         final Object[] items = this.items;
19         items[putIndex] = x;
20         if (++putIndex == items.length)
21             putIndex = 0;
22         count++;
23         //这个时候队列非空了
24         notEmpty.signal();
25     }

队列取元素:

 1     public E take() throws InterruptedException {
 2         final ReentrantLock lock = this.lock;
 3         //同步锁开启
 4         lock.lockInterruptibly();
 5         try {
 6             //队列为空,进行以空条件阻塞,直到有元素导致notEmpty.signal
 7             while (count == 0)
 8                 notEmpty.await();
 9             //取元素
10             return dequeue();
11         } finally {
12             lock.unlock();
13         }
14     }
15 
16     private E dequeue() {
17         final Object[] items = this.items;
18         @SuppressWarnings("unchecked")
19         E x = (E) items[takeIndex];
20         items[takeIndex] = null;
21         if (++takeIndex == items.length)
22             takeIndex = 0;
23         count--;
24         if (itrs != null)
25             itrs.elementDequeued();
26         //这个时候队列不满了
27         notFull.signal();
28         return x;
29     }

那么`ReentrantLock`的`Condition`又是如何来实现当前线程的等待的呢。
通过`ReentrantLock`源码可以发现,其内部定义了一个方法:

1     public Condition newCondition() {
2         return sync.newCondition();
3     }

sync是其内部类,并且继承了抽象类 `AbstractQueuedSynchronizer`,sync整个构建NewCondition的过程,其实是初始化了
AbstractQueuedSynchronizer的一个内部类:`ConditionObject`

AQS参考:【http://blog.csdn.net/aesop_wubo/article/details/7555956】

那么ConditionObject又做了什么,来实现等待和唤醒的过程的呢。
问题就转到类ConditionObject的两个方法的分析上:await/signal。

await方法,构建一个等待链表,以当前线程为“键”,并且中断当前线程:

 1  public final void await() throws InterruptedException {
 2             if (Thread.interrupted())
 3                 throw new InterruptedException();
 4 
 5             //构建Waiter等待现场链表,Node内以当前线程对象为键
 6             Node node = addConditionWaiter();
 7 
 8             //以下代码对node节点的线程进行相关状态的判断,最终是执行了线程的
 9             // LockSupport.park(this);方法,也就是阻塞线程
10 
11             int savedState = fullyRelease(node);
12             int interruptMode = 0;
13             while (!isOnSyncQueue(node)) {
14                 LockSupport.park(this);
15                 if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
16                     break;
17             }
18             if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
19                 interruptMode = REINTERRUPT;
20             if (node.nextWaiter != null) // clean up if cancelled
21                 unlinkCancelledWaiters();
22             if (interruptMode != 0)
23                 reportInterruptAfterWait(interruptMode);
24 
25         }
26 
27         private Node addConditionWaiter() {
28             Node t = lastWaiter;
29             // If lastWaiter is cancelled, clean out.
30             if (t != null && t.waitStatus != Node.CONDITION) {
31                 unlinkCancelledWaiters();
32                 t = lastWaiter;
33             }
34             Node node = new Node(Thread.currentThread(), Node.CONDITION);
35             if (t == null)
36                 firstWaiter = node;
37             else
38                 t.nextWaiter = node;
39             lastWaiter = node;
40             return node;
41         }

signal:内部遍历了等待链表,以CAS的方式修改节点状态,并且唤醒等待线程。

 1         public final void signal() {
 2             if (!isHeldExclusively())
 3                 throw new IllegalMonitorStateException();
 4             Node first = firstWaiter;
 5             if (first != null)
 6                 doSignal(first);
 7         }
 8 
 9         private void doSignal(Node first) {
10             do {
11                 if ( (firstWaiter = first.nextWaiter) == null)
12                     lastWaiter = null;
13                 first.nextWaiter = null;
14             } while (!transferForSignal(first) &&
15                      (first = firstWaiter) != null);
16         }
17 
18     final boolean transferForSignal(Node node) {
19 
20         if (!compareAndSetWaitStatus(node, Node.CONDITION, 0))
21             return false;
22 
23         Node p = enq(node);
24         int ws = p.waitStatus;
25         //唤醒了等待线程
26         if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
27             LockSupport.unpark(node.thread);
28         return true;
29     }

自此,阻塞队列ArrayBlockingQueue其实底层还是用到了ReentrantLock类和AbstractQueuedSynchronizer的锁机制来实现,无非是高层的引用类罢了。

 

posted @ 2018-03-13 13:50  Atomm  阅读(139)  评论(0编辑  收藏  举报