ArrayBlockingQueue源码分析
Posted 本站大佬
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ArrayBlockingQueue源码分析相关的知识,希望对你有一定的参考价值。
构造方法:
方法 | 作用 |
---|---|
add | 增加数据,如果阻塞队列为满,则返回false |
put | 增加数据,如果阻塞队列为满,则等待 |
poll无超时时间 | 如果队列为空,则返回null |
poll有超时时间 | 如果队列为空,则等待时间,超过等待时间,仍然为空,则返回null |
take | 在取出数据时,如果队列为空,则会等待 |
remainingCapacity | 返回队列剩余容量 |
size | 返回队列中数据的长度 |
remove | 取出队列中指定的Object |
contains | 返回队列中是否含有某个对象 |
//一次性写入一个集合的数据
public ArrayBlockingQueue(int capacity, boolean fair,
Collection<? extends E> c)
this(capacity, fair);
//final ReentrantLock lock;获取到这把锁
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为0.
putIndex = (i == capacity) ? 0 : i;
finally
lock.unlock();
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();
public ArrayBlockingQueue(int capacity)
this(capacity, false);
添加元素add
public boolean add(E e)
return super.add(e);
public boolean add(E e)
//在添加元素时调用offer方法。
if (offer(e))
return true;
else
throw new IllegalStateException("Queue full");
public boolean offer(E e)
checkNotNull(e);
//获取全局锁
final ReentrantLock lock = this.lock;
lock.lock();
try
if (count == items.length)
return false;
else
//将满足条件的数据存入阻塞队列。
enqueue(e);
return true;
finally
lock.unlock();
private void enqueue(E x)
// assert lock.getHoldCount() == 1;
// assert items[putIndex] == null;
final Object[] items = this.items;
items[putIndex] = x;
if (++putIndex == items.length)
putIndex = 0;
count++;
//通知不为空锁解开。
notEmpty.signal();
添加元素put(分析源码可知,put遇到满队列时,会进入等待状态。而add不会。)
public void put(E e) throws InterruptedException
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try
while (count == items.length)
notFull.await();
enqueue(e);
finally
lock.unlock();
取出数据
public E poll(long timeout, TimeUnit unit) throws InterruptedException
long nanos = unit.toNanos(timeout);
final ReentrantLock lock = this.lock;
//这个方法设置了超时时间,当获得锁后会进行判断,队列中是否有数据。如果没有则等待所设置的时间。
lock.lockInterruptibly();
try
while (count == 0)
if (nanos <= 0)
return null;
nanos = notEmpty.awaitNanos(nanos);
return dequeue();
finally
lock.unlock();
public E poll()
final ReentrantLock lock = this.lock;
lock.lock();
try
//如果阻塞队列中没有数据的话则返回null。
return (count == 0) ? null : dequeue();
finally
lock.unlock();
private E dequeue()
// assert lock.getHoldCount() == 1;
// assert items[takeIndex] != null;
final Object[] items = this.items;
@SuppressWarnings("unchecked")
E x = (E) items[takeIndex];
items[takeIndex] = null;
if (++takeIndex == items.length)
takeIndex = 0;
count--;
if (itrs != null)
itrs.elementDequeued();
notFull.signal();
return x;
take方法在取出数据时,如果队列为空,则会等待。
public E take() throws InterruptedException
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try
while (count == 0)
notEmpty.await();
return dequeue();
finally
lock.unlock();
以上是关于ArrayBlockingQueue源码分析的主要内容,如果未能解决你的问题,请参考以下文章