java queue put take_java blockingqueue原理是什么?原理详解

本文详细介绍了Java中的BlockingQueue接口及其常用实现类,如ArrayBlockingQueue。 BlockingQueue基于ReentrantLock实现了两个Condition,用于协调生产者和消费者的同步。当队列满时,put操作会被阻塞,而队列空时,take操作会被阻塞,通过signal()方法唤醒等待的线程。这种机制在实现生产者消费者模式中非常关键。
摘要由CSDN通过智能技术生成

你知道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)

49b37aa929db3ba84eea18ce6e050f5c.png

take()

b98e438410c3a986613ec58c4af2aa34.png

在这当中,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工具网来进行了解哦。

推荐阅读:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值