你知道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. < E > 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工具网来进行了解哦。
推荐阅读: