Java 队列总结
通过前面文章的学习, 我们对 Java 中常用队列做了介绍. 本文, 咱们来对队列做个总结吧.
首先, 我们介绍了现实生活中的实际场景(排队买票等), 来告诉我们为什么需要使用队列.
队列是一种先进先出 (FIFO) 的抽象数据结构, 在 Java 中, 队列使用了两种数据类型来实现的, 分别是: 数组和链表这两种数据结构.
本文主要内容: 回顾 Java 中常用的七个阻塞队列进行总结及阻塞队列中四组 AP 并进行总结.
接着, 我们介绍了队列的分类, 可以分为两类, 即阻塞队列和非阻塞队列.
常用的三个非阻塞队列: LinkedList,PriorityQueue 和 ConcurrentLinkedQueue.
(PS: 凯哥没有做介绍, 在以后的文章中, 凯哥将对 ConcurrentLinkedQueue 进行介绍)
然后我们介绍 Java 中常用的七个阻塞队列. 他们之间类图关系:
我们可以看到, 队列是 Collection 的子类. 也即和 arrayList 类似的.
接着我们就对七个阻塞队列做了详细的介绍.
阻塞队列的七个子类
ArrayBlockingQueue(下文简称: ABQueue),LinkedBlockingQueue(下文简称: LBQueue),PriorityBlockingQueue(下文简称: PBQueue),DelayQueue(下文简称: DQueue),SynchronouseQueue(下文简称: SyncQueue),LinkedTrnsferQueue(下文简称: LTQueue),LinkedBlockingDeque(下文简称: LBDeque)这个七个.
来分别说说每个队列的特点:
ABQueue:
底层使用的是数组结构. 因为数组需要初始化大小, 所以其构造器需要输入队列的大小.
是有界的阻塞安全队列(思考: 为什么说是有界的? 是怎么保证线程安全的?), 默认是不保证线程的公平性(思考: 为什么默认不能保证线程公平? 如何保证线程安全?), 不允许向队列中插入 null 元素.
LBQueue:
"有界" 的阻塞安全队列, 其底层使用的是链表的数据结构. 所谓的 "有界" 是因为, 默认队列的大小是 Integer.MAX_VALUE. 这个数值等于 21 亿 +. 因为这个数据太大了, 也可以理解为无界的. 不建议使用默认值, 最好在初始化的时候, 指定队列的大小.
PBQueue:
是一个支持优先级的无界队列. 支持优先级是因为使用了 comparator 这个接口. 默认采用字典升序排序策略的. 如果不想使用默认的, 在初始化的时候, 还可以自定义比较器的.
以上三个队列相关更详细的介绍, 欢迎回看《Java 中常用的七个阻塞队列介绍第一篇》. 在这篇文章中, 凯哥对这三个队列做了详细的介绍以及代码演示.
DQueue:
是一个支持优先级的无界阻塞队列. 支持优先级是应该底层使用的是 PriorityQueue 队列来实现的. 而 PriorityQueue 队列在添加元素的时候使用了 siftUpComparable 方法. 这个对了的一个特点: 支持延时获取. 所以, 这个队列可以运用在缓存系统的设计中. 当从队列中获取到数据, 说明延时时间到了.
关于 DQueue 更多详细的介绍, 欢迎回看:《Java 中常用的七个阻塞队列第二篇 DelayQueue 源码介绍》. 在这篇文章中, 凯哥做了详细的介绍, 同时使用代码模拟了缓存数据到期操作.
SyncQueue:
是一个无存储空间的阻塞同步队列. 不存储元素的原因是因为, 一个 put 操作必须等待一个 take 操作与之对应才可以. 否则就不能继续添加元素了. 默认使用非公平的. 在性能上 SyncQueue 队列的吞吐量比 LBqueu 和 ABQueue 的性能高.
LTQueue: 是由链表组成的无界队列. 比其他队列多了两个方法: tryTransfer,transfer
LBDeque: 链表组成的双端队列. 这个队列在以后凯哥讲 For/Join 框架的时候, 还会说到.
七个阻塞队列的小总结:
接着, 我们讲解了队列中常用的四组 API.
阻塞队列四组 API
会抛异常的: 添加元素使用 add(e), 删除元素使用 remove, 检查队首元素使用的 element.
当队列满的时候, 在向队列中添加元素会抛出异常; 当队列为空的时候在从队列中删除或者是获取队首元素都会抛出异常;
带有返回值的: 添加元素: offer(e), 删除元素: poll(), 检查队首元素: peek().
当队列满的时候, 再调用 offer(e)向队列中添加元素会返回 false 而不是抛出异常
当队列为空的时候, 调用 take()或者是 peek()方法返回 null 而不是抛出异常
阻塞一直等待的: 添加元素: put(e), 删除元素: take()
当队列满的时候, 再向队列中添加元素, 队列会进入阻塞状态, 直到元素添加成功为止.
当队列为空的时候, 再从队列删除元素, 队列会阻塞, 直到能够删除元素为止.
带有超时时间的阻塞: 添加元素: offer(e,time,unit), 删除元素: poll(time,unit)
当队列满的时候, 调用 offer(e,time,unit)会进入阻塞等待中, 当过来超时时间, 退出等待
当队列为空的时候, 调用 poll(time,unit)方法会进入等待状态, 当到了超时时间, 会退出等待.
四组 API 总结:
关于四组 API 更详细的介绍欢迎学习:《Java 阻塞队列的四组 API》. 在这篇文章中凯哥做了详细的介绍. 用人的一生四个阶段来比拟这四组 API.
到此, 我们已经把 Java 中队列介绍完毕. 接下来, 凯哥将带着大家一起学习线程池. 欢迎大家继续学习.
来源: https://www.cnblogs.com/kaigejava/p/12825493.html