1 阻塞队列定义
阻塞队列是一个在队列基础上又支持了两个附加操作的队列。
支持阻塞的插入:队列满时,队列会阻塞插入元素的线程,指导队列未满;
支持阻塞的移除:队列空时,获取元素的线程会阻塞,指导队列变为非空;
阻塞队列方法可以总结为如下所示:
方法处理方式 | 抛出异常 | 返回特殊值 | 一直阻塞 | 超时退出 |
---|---|---|---|---|
插入方法 | add(e) | offer(e) | put(e) | offer(e,time,unit) |
移除方法 | remove() | poll() | take() | poll(time,unit) |
检查方法 | element() | peek() | 不可用 | 不可用 |
2 BlockingQueue继承关系
poll -->【若队列为空,返回null】
remove >【若队列为空,抛出NoSuchElementException异常】
take -->【若队列为空,发生阻塞,等待有元素】
java7提供了7个阻塞队列,这里引用了博客的说明:
3 LinkedBlockingQueue代码解析
下文对于主要的入队和出队阻塞操作进行了说明,至于非阻塞类型的操作暂时不予讨论!
3.1 入队操作put
如图为put操作过程,如果达到队列容量则调用condition await阻塞线程!
注意这里是使用的条件监听器Contion的变量notFull!!!
3.2 出队操作take
出队操作是使用的notEmpty完成线程阻塞,另外每次入队后检查一下具体队列个数,如果队列还有值则发送一次非空信号!
3.3 未满信号发送
这里关注一下未满信号的具体发送位置!
3.4 未空信号发送
下图主要列出了非空状态监听器发送激活signal的的几个地方,这里重点提一下signalNotEmpty和signalNotFull:当队列初始状态为空或者已经满的情况下,使用的状态c会等于0或者capacity,这种情况下完成put或者take操作有必要告知出现了非空或者未满的情况!因此需要发送信号!
c == capacity或者c == 0
这个是因为cas操作是先get再增长或者减少,因此初识状态得以保存!