你知道java当中blockingqueue原理吗?很多人表示对于blockingqueue的原理不大清楚,那么接下来就一起通过下面的文章内容来了解一下吧。
blockingqueue也就是我们经常说的阻塞队列,根据blockingqueue的基本原理,可以实现Web当中的长连接聊天功能,但是,比较常用的还是用在实现生产者和消费者模式。
在java当中,blockingqueue是一个接口,实现类有ArrayBlockingQueue、DelayQueue、
LinkedBlockingDeque、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue等等。
blockingqueue的内部有一个ReentrantLock,它生成了2个Condition,在ArrayBlockingQueue的属性声明当中,能够看见。/** Main lock guarding all access */
final ReentrantLock lock;
/** Condition for waiting takes */
private final Condition notEmpty;
/** Condition for waiting puts */
private final Condition notFull;
...
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();
}
假如,能够将notEmpty、notFull、put线程、take线程拟人的话,那么,put和take操作很有可能是下面这样的:
put(e)
take()
在这当中,ArrayBlockingQueue.put(E e)源码如下:/**
* Inserts the specified element at the tail of this queue, waiting
* for space to become available if the queue is full.
*
* @throws InterruptedException {@inheritDoc}
* @throws NullPointerException {@inheritDoc}
*/
public void put(E e) throws InterruptedException
{
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try
{
while (count == items.length)
notFull.await(); // 如果队列已满,则等待
insert(e);
}
finally
{
lock.unlock();
}
}
/**
* Inserts element at current put position, advances, and signals.
* Call only when holding lock.
*/
private void insert(E x)
{
items[putIndex] = x;
putIndex = inc(putIndex);
++count;
notEmpty.signal(); // 有新的元素被插入,通知等待中的取走元素线程
}
ArrayBlockingQueue.take()源码如下:public E take() throws InterruptedException
{
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try
{
while (count == 0)
notEmpty.await(); // 如果队列为空,则等待
return extract();
}
finally
{
lock.unlock();
}
}
/**
* Extracts element at current take position, advances, and signals.
* Call only when holding lock.
*/
private E extract()
{
final Object[] items = this.items;
E x = this. cast(items[takeIndex]);
items[takeIndex] = null;
takeIndex = inc(takeIndex);
--count;
notFull.signal(); // 有新的元素被取走,通知等待中的插入元素线程
return x;
}
这里可以知道,put(E)和take()是同步的。
在put操作当中,队列满了,会阻塞put操作,直到队列中有空闲的位置,在take操作当中,队列是空的时候,会阻塞take操作,一直到队列当中有新的元素。
这里是话使用2个Condition,这样是能够调用signal()的时候,会唤醒相同的put或者是take操作。
对于blockingqueue的基本原理就给你介绍到这里了,你都了解了吗?更多blockingqueue常见问题,可以继续关注奇Q工具网来进行了解哦。
推荐阅读: