Java 阻塞队列总结与常见面试题
2020-07-17 本文已影响0人
爱打乒乓的程序员
1.常用的阻塞队列有哪些?
ArrayBlockingQueue、LinkedBlockingQueue、DelayQueue、SynchronousQueue 、PriorityQueue等
2.它们各自的区别是什么?
常见的阻塞队列 | 数据结构 | 是否有界 | 线程安全 | 使用场景 | 如何阻塞 |
---|---|---|---|---|---|
ArrayBlockingQueue | 数组 | 有界 | 使用ReentrantLock保证出入队线程安全 | 一般用于生产数据固定的场景 | 1.当队列为空,take操作会阻塞;poll操作加上超时时间也会阻塞,直到超时后返回null 2.当队列满的时候,put操作会阻塞;offer操作加上超时时间也会阻塞,直到超时后返回false |
LinkedBlockingQueue | 链表 | 无界 | 使用ReentrantLock分别作为读写锁保证出入队线程安全 | 适合对生产的数据大小不定(时高时低),数据量较大的场景 | 与 ArrayBlockingQueue 的阻塞原理相似 |
PriorityBlockingQueue | 二叉堆 | 无界 | 使用ReentrantLock保证出入队线程安全 | 排序阻塞操作 | 队列是无界的,所以添加元素不会阻塞。只有当队列为空的时候,take操作会阻塞;poll操作加上超时时间也会阻塞,直到超时后返回null |
DelayQueue | 二叉堆 | 无界 | 使用ReentrantLock保证出入队线程安全 | 延迟阻塞操作 | 与 PriorityBlockingQueue 的阻塞原理相似 |
SynchronousQueue | 队列或堆栈 | 无容量概念 | 使用CAS保证出入队线程安全 | CachedThreadPool线程池使用 | 当前操作与队列或堆栈中第一个数据操作一样的话就会一直阻塞,只有当队列中两个操作是互补的状态才会出队 |
3.无锁队列的原理是什么?
SynchronousQueue 队列是无锁队列,其内部是使用CAS自旋操作保证线程安全
4.延迟阻塞队列的原理是什么?
DelayQueue 底层使用了 PriorityQueue 优先级队列,而 PriorityQueue 实际上一个二叉堆结构,通过比较堆内元素过期时间,将堆内最快过期的元素放在堆头,以保证每次获取的元素是最二叉堆中最快过期的元素
5.String变量可以放在 DelayQueue 队列里面吗?
DelayQueue 要求元素必须实现 Delayed 接口,也就是说 DelayQueue 的元素必须是 Delayed 的子类。而String类并没有实现 Delayed 接口,所以String 变量是不能放在 DelayQueue 队列里。
6.如何查看 SynchronousQueue 队列的大小?
实际上 SynchronousQueue 本身是没有容量的,所以也无法查看其容量的大小,其内部的 size 方法都是写死的返回 0
7.如果超出 LinkedBlockingQueue 的容量值,又会出现什么情况?
如果有限定 LinkedBlockingQueue 的容量,当达到容量值的时候put操作和offer操作加上超时时间会阻塞;如果没有限定容量的话,就可认为容量是无限大,直到耗尽机器的资源,发生OOM。所以我们在使用 LinkedBlockingQueue 的时候最好能够设置容量,防止耗尽内容!