一,概述
消费者生产者经典阻塞队列,其定义是,如果队列已满,阻塞生产者添加元素到队列;如果队列为空,阻塞消费者从队列中取元素。阻塞方法是put和take,非阻塞方法是offer和poll

代表实现是LinkedBlockQueue
二,实现
LinkedBlockQueue
offer

1,put锁#lock
2,如果队列已满,使用notFull.awaitNaos阻塞offer操作,put方法在此处同理,只是无超时参数。
3,新Node节点入队
4,如果队列未满,则唤醒其他生产者(串行唤醒)
5,如果getAndIncrement返回的是0,则代表队列此前为空,则通过notEmpty唤醒第一个await节点的消费者
take

1,take锁#lock
2,如果队列空,阻塞take
3,出队
4,唤醒其它消费者线程(串行唤醒)
5,如果getAndDecrement前已经满,此前的put操作存在阻塞,因此通过notFull唤醒第一个await节点的生产者
ArrayBlockQueue
put


1,lock
2,达到最大长度,await挂起
3,入队
4,enqueue后,便调用notEmpty唤醒一个消费者
take


1,lock
2,队列为空,await挂起
3,出队
4,只要出队,便唤醒一个生产者
对比总结
特性 | ArrayBlockingQueue | LinkedBlockingQueue |
---|---|---|
底层实现 | 数组 | 链表 |
容量 | 固定 | 可指定容量,也可动态增长 |
锁设计 | 单锁 | 双锁 |
性能 | 高性能,适合高并发场景 | 性能稍逊,但适合生产者和消费者分离的场景 |
内存占用 | 低,占用固定内存 | 高,占用动态分配的内存 |
适用场景 | 数据量可控、内存敏感、性能要求高的场景 | 数据量不确定、高并发、内存不敏感的场景 |