标题:
Java 容器源码分析之ArrayBlockingQueue和LinkedBlockingQueue(1)
[打印本页]
作者:
look_w
时间:
2019-1-11 18:32
标题:
Java 容器源码分析之ArrayBlockingQueue和LinkedBlockingQueue(1)
Java中的阻塞队列接口BlockingQueue继承自Queue接口。
BlockingQueue接口提供了3个添加元素方法。
add:添加元素到队列里,添加成功返回true,由于容量满了添加失败会抛出IllegalStateException异常
offer:添加元素到队列里,添加成功返回true,添加失败返回false
put:添加元素到队列里,如果容量满了会阻塞直到容量不满
3个删除方法。
poll:删除队列头部元素,如果队列为空,返回null。否则返回元素。
remove:基于对象找到对应的元素,并删除。删除成功返回true,否则返回false
take:删除队列头部元素,如果队列为空,一直阻塞到队列有元素并删除
常用的阻塞队列具体类有ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue、LinkedBlockingDeque等。
本文以ArrayBlockingQueue和LinkedBlockingQueue为例,分析它们的实现原理。
ArrayBlockingQueueArrayBlockingQueue的原理就是使用一个可重入锁和这个锁生成的两个条件对象进行并发控制(classic two-condition algorithm)。
ArrayBlockingQueue是一个带有长度的阻塞队列,初始化的时候必须要指定队列长度,且指定长度之后不允许进行修改。
它带有的属性如下:
//
存储队列元素的数组,是个循环数组
final
Object[] items;
//
拿数据的索引,用于take,poll,peek,remove方法
int
takeIndex;
//
放数据的索引,用于put,offer,add方法
int
putIndex;
//
元素个数
int
count;
//
可重入锁
final
ReentrantLock lock;
//
notEmpty条件对象,由lock创建
private
final
Condition notEmpty;
//
notFull条件对象,由lock创建
private
final
Condition notFull;
数据的添加ArrayBlockingQueue有不同的几个数据添加方法,add、offer、put方法。
add方法:
public
boolean
add(E e) {
if
(offer(e))
return
true
;
else
throw
new
IllegalStateException("Queue full"
);}
add方法内部调用offer方法如下:
public
boolean
offer(E e) { checkNotNull(e);
//
不允许元素为空
final
ReentrantLock lock =
this
.lock; lock.lock();
//
加锁,保证调用offer方法的时候只有1个线程
try
{
if
(count == items.length)
//
如果队列已满
return
false
;
//
直接返回false,添加失败
else
{ insert(e);
//
数组没满的话调用insert方法
return
true
;
//
返回true,添加成功
} }
finally
{ lock.unlock();
//
释放锁,让其他线程可以调用offer方法
}}
insert方法如下:
private
void
insert(E x) { items[putIndex]
= x;
//
元素添加到数组里
putIndex = inc(putIndex);
//
放数据索引+1,当索引满了变成0
++count;
//
元素个数+1
notEmpty.signal();
//
使用条件对象notEmpty通知,比如使用take方法的时候队列里没有数据,被阻塞。这个时候队列insert了一条数据,需要调用signal进行通知
}
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0