LinkedBlockQueue生产消费源码解析

时间:2023-03-10 03:05:15
LinkedBlockQueue生产消费源码解析

LinkedBlockQueue自JDK1.5以后提供的一种阻塞队列,遵循生产者消费者模式,实现了BlockQueue接口,如图

LinkedBlockQueue生产消费源码解析

从它的名字可以了解到它是采用链表的方式实现了阻塞队列,并且定义了“节点”的内部类,如图

LinkedBlockQueue生产消费源码解析

我们看到,每个Node当中除了Node的数据item以外只有一个next节点来指向下一个节点。

另外LinkedBlockQueue在实现里采用了ReentrantLock来控制生产和消费等操作的并发情况,并且采用关联的Condition来做阻塞等待,所以它是线程安全的。

LinkedBlockQueue生产消费源码解析

DEMO

接下来,我们把LinkedBlockQueue的DEMO作为入口,代码如下

LinkedBlockQueue生产消费源码解析

构造方法

构造方法允许指定队列最大容量,如果不指定则采用INT的最大值。所以LinkedBlockQueue实际上也属于有界队列,只是它的默认队列容量很大,一般情况下不会出现超过容量的情况。

LinkedBlockQueue生产消费源码解析

LinkedBlockQueue定义了head和last节点分别表示起始和结束,是一种双端链表的实现方式,head的item永远为null,last的next永远为null,当队列为空的时候head节点和last节点指向一个空的Node

LinkedBlockQueue生产消费源码解析

生产操作offer(E e)

offer(E e)方法仅提供一个数据入参,如果容量未满则入队,如果满了那么直接结束。

LinkedBlockQueue生产消费源码解析

入队方法很简单,就是将当前最后一个节点的next指向新的节点,并且新的节点成为最后一个节点

LinkedBlockQueue生产消费源码解析

生产操作offer(E e, long timeout, TimeUnit unit)

该方法与普通offer方法的区别在于提供了超时时间,也就是说在没有空间可以增加元素的时候会进行阻塞等待,这里采用Condition的方式实现

LinkedBlockQueue生产消费源码解析

生产操作put(E e)

put方法跟offer的区别在于,如果没有足够的空间put会一直等待直到中断或者有空间

LinkedBlockQueue生产消费源码解析

消费操作poll()

poll操作不会进行等待,如果没有待消费的元素,那么直接返回

LinkedBlockQueue生产消费源码解析

出队操作就是把当前的第一个head节点的next指向自己,真正的第一个node节点成为head节点

LinkedBlockQueue生产消费源码解析

消费操作poll(long timeout, TimeUnit unit)

如果没有待消费的数据,该方法会进行等待,直到有消费数据或者中断

LinkedBlockQueue生产消费源码解析

消费操作take()

跟put类似take是一个会一直等待的操作,如果没有待消费的数据那么就阻塞直到中断或者消费到数据

LinkedBlockQueue生产消费源码解析

LinkedBlockQueue在的生产和消费操作是通过互斥锁来控制并发的,也就是同时只会有一个生产操作或者一个消费操作,当生产操作完成会通知等待消费线程,消费操作完成会通知等待生产的线程。