ArrayBlockingQueue相对来说就比较简单了。
ArrayBlockingQueue是基于数组的阻塞队列,创立的时候须要指定容量,也就是说ArrayBlockingQueue是有界队列。
ArrayBlockingQueue#次要属性
items:也就是ArrayBlockingQueue的底层数据结构
final Object[] items;
takeIndex:下次出队列的地位,包含take, poll, peek or remove等操作。
putIndex:下次入队列的地位,包含put, offer, or add等操作。
count:队列理论长度。
lock:ReentrantLock,出、入队列的时候都须要上锁。
notEmpty:lock的Condition,帮助获取数据的线程排队。
notFull:lock的Condition,帮助退出队列的线程排队。
构造方法
采纳非偏心锁创立容量为capacity的队列:
public ArrayBlockingQueue(int capacity) { this(capacity, false); }
创立容量为capacity的队列,fair参数指定应用偏心锁或非偏心锁:
public ArrayBlockingQueue(int capacity, boolean fair) { if (capacity <= 0) throw new IllegalArgumentException(); this.items = new Object[capacity]; lock = new ReentrantLock(fair); notEmpty = lock.newCondition(); notFull = lock.newCondition(); }
创立一个非空的队列,如果初始化汇合容量超过了指定的队列容量则抛出异样,初始化数据的过程中统计队列理论容量count、以及putIndex:
public ArrayBlockingQueue(int capacity, boolean fair, Collection<? extends E> c) { this(capacity, fair); final ReentrantLock lock = this.lock; lock.lock(); // Lock only for visibility, not mutual exclusion try { int i = 0; try { for (E e : c) { checkNotNull(e); items[i++] = e; } } catch (ArrayIndexOutOfBoundsException ex) { throw new IllegalArgumentException(); } count = i; putIndex = (i == capacity) ? 0 : i; } finally { lock.unlock(); } }
入队和出队
与LinkedBlockingQueue相似,ArrayBlockingQueue也提供了两类出队、入队办法。
阻塞办法:put,take。
非阻塞办法:add、offer、poll, peek ,remove。
阻塞办法put在队列满的时候通过notFull、take在队列空的时候通过notEmpty阻塞以后线程,直到条件满足再唤醒返回。
非阻塞的入队办法在队列未满是实现入队返回true、队列满的话立刻返回false。非阻塞的出队办法在队列空的时候立刻返回null。
加锁、阻塞、唤醒形式与LinkedBlockingQueue大同小异,所以代码就不贴出了。
不过ArrayBlockingQueue的入队和出队采纳了一个比拟奇妙的算法:putIndex、takeIndex、count初始化为0,每入队一个元素则putIndex++、count++,putIndex达到队列容量item.length后再从0开始。takeIndex的操作逻辑相似,每出队一个元素则takeIndex++、count--,takeIndex达到队列容量后再从0开始。
每次入队的时候都会查看队列容量是否容许以后元素入队,这样就能确保putIndex、takeIndex始终保持在一个正确的地位,他们两个就像是在一段长度无限的笔挺公路上始终同向、重复循环行驶的小汽车,在count的协调下他们两个永远不会相遇。
区别
简略说一下SynchronousQueue、LinkedBlockingQueue和ArrayBlockingQueue的不言而喻的区别或者说各自的特点,不肯定全面:
- 首先他们都是BlockingQueue,是线程平安的,多线程环境下能够放心大胆应用
- SynchronousQueue是无界队列,队列中保留的是生产者生产的数据、或者是消费者的获取数据的申请,只提供阻塞办法(底层都是通过transfer实现的)
- LinkedBlockingQueue的底层是列表构造,能够是有界的、也能够是无界的,队列中只存储生产者的数据。提供阻塞和非阻塞两种入队、出队操作,通过可重入锁的Condition来阻塞线程
- ArrayBlockingQueue的底层是数组,是有界队列,队列中只存储生产者的数据。提供阻塞和非阻塞两种入队、出队操作,通过可重入锁的Condition来阻塞线程
小结
三种BlockingQueue的源码剖析结束,接下来能够开始学习线程池ThreadPoolExecutor的相干内容了。
Thanks a lot!
上一篇 BlockingQueue - LinkedBlockingQueue