1. 阻塞队列介绍
顾名思义,阻塞队列是一个具备先进先出特性的队列结构,从队列末尾插入数据,从队列头部取出数据。而阻塞队列与普通队列的最大不同在于阻塞队列提供了阻塞式的同步插入、取出数据的功能(阻塞入队put/阻塞出队take)。
使用 put插入数据时,如果队列空间已满并不直接返回,而是令当前操作的线程陷入阻塞态(生产者线程),等待着阻塞队列中的元素被其它线程(消费者线程)取走,令队列重新变得不满时被唤醒再次尝试插入数据。使用 take取出数据时,如果队列空间为空并不直接返回,而是令当前操作的线程陷入阻塞态(消费者线程),等待其它线程(生产者线程)插入新元素,令队列非空时被唤醒再次尝试取出数据。
阻塞队列主要用于解决并发场景下消费者线程与生产者线程处理速度不一致的问题。例如jdk的线程池实现中,线程池核心线程(消费者线程)处理速度一定的情况下,如果业务方线程提交的任务过多导致核心线程处理不过来时,将任务暂时放进阻塞队列等待核心线程消费(阻塞队列未满);由于核心线程常驻的原因,当业务方线程提交的任务较少,核心线程消费速度高于业务方生产速度时,核心线程作为消费者会阻塞在阻塞队列的take方法中,避免无谓的浪费cpu资源。
由于阻塞队列在内部实现了协调生产者/消费者的机制而不需要外部使用者过多的考虑并发同步问题,极大的降低了生产者/消费者场景下程序的复杂度。
2. 自己实现阻塞队列
接下来,我们从低效率到高效率逐步实现几种不同版本的阻塞队列,以加深我们对阻塞队列工作原理的理解。
[En]
Next, we implement several different versions of blocking queues from low to high efficiency step by step to deepen our understanding of the working principle of blocking queues.
阻塞队列接口
为了降低复杂性,我们的阻塞队列只提供了最基本的出队、排队和空接口。
[En]
In order to reduce complexity, our blocking queue only provides the most basic dequeuing, queuing and null interfaces.
```
/**