Java 阻塞队列总结

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 的时候最好能够设置容量,防止耗尽内容!

你可能感兴趣的:(Java 阻塞队列总结)