前言
BlockingQueue
即阻塞队列,它算是一种将ReentrantLock
用得非常精彩的一种表现,依据它的基本原理,我们可以实现Web中的长连接聊天功能,当然其最常用的还是用于实现生产者与消费者模式,大致如下图所示:
在Java中,BlockingQueue
是一个接口,它的实现类有ArrayBlockingQueue
、DelayQueue
、 LinkedBlockingDeque
、LinkedBlockingQueue
、PriorityBlockingQueue
、SynchronousQueue
等,它们的区别主要体现在存储结构上或对元素操作上的不同,但是对于take与put操作的原理,却是类似的。下面的源码以ArrayBlockingQueue
为例。
分析
BlockingQueue
内部有一个ReentrantLock
,其生成了两个Condition
,在ArrayBlockingQueue
的属性声明中可以看见:
1 | /** Main lock guarding all access */ |
而如果能把notEmpty
、notFull
、put
线程、take
线程拟人的话,那么我想put
与take
操作可能会是下面这种流程:
put(e)
take()
其中ArrayBlockingQueue.put(E e)
源码如下(其中中文注释为自定义注释,下同):
1 | /** |
ArrayBlockingQueue.take()
源码如下:
1 | public E take() throws InterruptedException { |
可以看见,put(E)与take()是同步的,在put操作中,当队列满了,会阻塞put操作,直到队列中有空闲的位置。而在take操作中,当队列为空时,会阻塞take操作,直到队列中有新的元素。
而这里使用两个Condition,则可以避免调用signal()时,会唤醒相同的put或take操作。
参考地址
如果大家喜欢我的文章,可以关注个人订阅号。欢迎随时留言、交流。如果想加入微信群的话一起讨论的话,请加管理员简栈文化-小助手(lastpass4u),他会拉你们进群。