问题
(1)之间的实现方式?
(2)之间是否需要扩容?
(3)之间有什么缺点吗?
简介
ArrayBlockingQueue是java并发包下一个以数组实现的阻塞队列,它是线程安全的,至于是否需要扩容,请看下面的分析。
队列
队列,是一种线性表,它的特点是先进先出,又叫FIFO,就像我们平常排队一样,先到先得,即先进入队列的人先出队。
源码分析
主要属性
<代码类="语言java ">//使用数组存储元素 最终对象[]项目;//取元素的指针 int takeIndex;//放元素的指针 int putIndex;//元素数量 int数;//保证并发访问的锁 最后ReentrantLock锁;//非空条件 私人notEmpty最终条件;//非满条件 私人notFull最终条件;代码>
通过属性我们可以得出以下几个重要信息:
(1)利用数组存储元素;
(2)通过放指针和取指针来标记下一次操作的位置;
(3)利用重入锁来保证并发安全;
主要构造方法
<代码类="语言java ">公共ArrayBlockingQueue (int能力){ 这(容量、假); } 公共ArrayBlockingQueue (int能力,布尔公平){ 如果(能力& lt;=0) 把新IllegalArgumentException ();//初始化数组 这一点。项=新对象(能力);//创建重入锁及两个条件 锁=新的ReentrantLock(公平); notEmpty=lock.newCondition (); notFull=lock.newCondition (); }代码>
通过构造方法我们可以得出以下两个结论:
(1) ArrayBlockingQueue初始化时必须传入容量,也就是数组的大小;
(2)可以通过构造方法控制重入锁的类型是公平锁还是非公平锁;
入队
入队有四个方法,它们分别是添加(E E),提供(E E),把(E E),提供(E E,长时间超时,TimeUnit unit),它们有什么区别呢?
<代码类="语言java ">公共逻辑加(E E) {//调用父类的add (e)方法 返回super.add (e); }//super.add (e) 公共逻辑加(E E) {//调用提供(e)如果成功返回真,如果失败抛出异常 如果(提供(e)) 返回true; 其他的 把新IllegalStateException(“队列已满”); } 公共布尔提供(E E) {//元素不可为空 checkNotNull (e); 最后ReentrantLock锁=this.lock;//加锁 lock.lock (); 尝试{ 如果(count==items.length)//如果数组满了就返回错误的 返回错误; 其他{//如果数组没满就调用入队方法并返回现实 排队(e); 返回true; } 最后}{//解锁 lock.unlock (); } } 公共空间把(E E)抛出InterruptedException { checkNotNull (e); 最后ReentrantLock锁=this.lock;//加锁,如果线程中断了抛出异常 lock.lockInterruptibly (); 尝试{//如果数组满了,使用notFull等待//notFull等待的意思是说现在队列满了//只有取走一个元素后,队列才不满//然后唤醒notFull,然后继续现在的逻辑//这里之所以使用,而不是如果//是因为有可能多个线程阻塞在锁上//即使唤醒了可能其它线程先一步修改了队列又变成满的了//这时候需要再次等待 而(count==items.length) notFull.await ();//入队 排队(e); 最后}{//解锁 lock.unlock (); } } 公共布尔提供(E E,长时间超时,TimeUnit单元) 抛出InterruptedException { checkNotNull (e); 长nano=unit.toNanos(超时); 最后ReentrantLock锁=this.lock;//加锁 lock.lockInterruptibly (); 尝试{//如果数组满了,就阻塞nano纳秒//如果唤醒这个线程时依然没有空间且时间到了就返回错误的 而(count==items.length) { 如果(nano & lt;=0) 返回错误; nano=notFull.awaitNanos (nano); }//入队 排队(e); 返回true; 最后}{//解锁 lock.unlock (); } } 私人空间排队(E x) { 最终对象[]项=this.items;//把元素直接放在放指针的位置上 项目[putIndex]=x;//如果放指针到数组尽头了,就返回头部 如果(+ + putIndex==items.length) putIndex=0;//数量加1 数+ +;//唤醒notEmpty,因为入队了一个元素,所以肯定不为空了 notEmpty.signal (); }代码>
(1)添加(e)时如果队列满了则抛出异常;
(2)提供(e)时如果队列满了则返回假;
(3)把(e)时如果队列满了则使用notFull等待;
(4)提供(e、超时、单元)时如果队列满了则等待一段时间后如果队列依然满就返回假;