-
总结一下java中的队列,主要是看jdk1.8.源码和java并发编程的艺术这本书
几种队列模型
- ArrayBlockQueue
-
数组实现的有界阻塞队列
-
可实现公平、非公平(默认)
-
公平性通过重入锁(ReentrantLock)实现。有lock成员变量
-
-
LinkBlockQueue
-
链表实现的有界阻塞队列
-
有默认长度和最大长度是Integer.MAX_VALUE
-
成员变量putLock、getLock两把锁
-
公平性?
-
-
PriorityBlockingQueue
-
支持优先级的无界阻塞队列(自动扩容实现无界,下面的无界队列同理)
-
默认是自然顺序排序,可以自定义compairTo()方法。入队的时候排序
-
成员变量lock
-
-
DelayQueue
-
延迟获取元素的无界阻塞队列
-
成员变量priorityQueue配合成员变量lock实现阻塞
-
元素 implements Delayed
-
实现getDelay接口,定义多久才能从队列中提取元素。take的时候会调用getDelay()方法
-
实现compareTo接口,定义元素顺序
-
成员变量leader用于优化获取队列头元素。leader不为空时,表示已有线程在等待获取头元素,采用await()方法让当前线程等待信号通知。leader为空时,将当前线程设置为leader,并使用awaitNanos()等待信号或delay时间
-
应用场景:缓存、定时任务调度
-
-
SynchronousQueue
-
不存储元素的阻塞队列
-
put操作需等待take操作
-
公平、非公平(默认)
-
静态内部类waitQueue中有成员变量lock
-
应用场景:传递手、生产消费模型
-
-
LinkTransferQueue
-
链表结构的无界阻塞TransferQueue
-
增加transfer()方法,当前有消费者正在接收(take,poll)元素时,可以用此方法立刻将生产者传入的元素transfer给消费者,如果没有则将生产的元素放入tail,自旋等待该元素被消费
-
增加tryTransfer()方法,类似于transfer(),不同在于try,如果没有消费者等待接受元素,则立刻返回。tryTransfer()可加时间限制
-
-
LinkBlockDeque
-
链表结构的双向阻塞队列
-
可在队列两端插入和移出元素
-
如何实现通知模式
-
何为通知模式:队列满时,生产者生产的时候会阻塞,直到消费者消费后通知生产者当前队列可用
-
ArrayBlockQueue为例实现
-
成员变量notFull、notEmpty是condition类型。
-
put的时候,当队列满时,循环等待notFull.await()的通知。clear、dequeue、remove会notFull.signal()
-
take的时候,当队列为空时,循环等待notEmpty.await()的通知。enqueue会notEmpty.signal()
-
condition是lock中的,类似于object的通知模型。
-
入队出队优化
-
设置head和tail节点,tail节点并不一直是队列最后一个元素。
-
入队:
-
1、入队节点设置成当前队列尾节点的下一个节点。2、更新tail节点,如果tail节点的下个节点不为空,则将入队节点设置为tail节点。反之,则将入队节点设置为tail的next节点。
-
寻找尾节点时,从tail节点往后寻找
-
好处:减少cas更新tail节点次数,提高入队效率
-
-
出队:
-
head中有元素时,直接弹出head中的元素,不更新head节点。head中没有元素时,更新head节点,弹出元素。这里的弹出元素,head->next依然指向下个节点
-
参考入队的思路
-