【并发编程】如何选择适合的阻塞队列
作者:互联网
常见阻塞队列
- ArrayBlockingQueue:基于数组结构实现的一个有界阻塞队列。
- LinkedBlockingQueue:基于链表结构实现的一个无界阻塞队列。
- PriorityBlockingQueue:支持按优先级排序的无界阻塞队列。
- DelayQueue:基于优先级队列(PriorityBlockingQueue)实现的无界阻塞队列。
- SynchronousQueue:不存储元素的阻塞队列。
- LinkedTransferQueue:基于链表结构实现的一个无界阻塞队列。
- LinkedBlockingDeque:基于链表结构实现的一个双端阻塞队列。
线程池默认选择的阻塞队列
- FixedThreadPool(SingleThreadExecutor 同理):选取的是 LinkedBlockingQueue。
- CachedThreadPool:选取的是 SynchronousQueue。
- ScheduledThreadPool(SingleThreadScheduledExecutor同理):选取的是延迟队列。
从功能角度考虑选择阻塞队列
- 比如是否需要阻塞队列帮我们排序,如优先级排序、延迟执行等。如果有这个需要,我们就必须选择类似于 PriorityBlockingQueue之类的有排序能力的阻塞队列。
从容量角度考虑选择阻塞队列
- 是否有存储的要求,还是只需要“直接传递”。
- 容量固定的:ArrayBlockingQueue;
- 容量无限的:LinkedBlockingQueue;
- 没有任何容量的:SynchronousQueue;
- 而对于 DelayQueue 而言,它的容量固定就是 Integer.MAX_VALUE。
从能否扩容角度考虑选择阻塞队列
- 有时我们并不能在初始的时候很好的准确估计队列的大小,因为业务可能有高峰期、低谷期。如果一开始就固定一个容量,可能无法应对所有的情况,也是不合适的,有可能需要动态扩容。
- 如果我们需要动态扩容的话,那么就不能选择 ArrayBlockingQueue ,因为它的容量在创建时就确定了,无法扩容。
- 相反,PriorityBlockingQueue 即使在指定了初始容量之后,后续如果有需要,也可以自动扩容。所以我们可以根据是否需要扩容来选取合适的队列。
从内存结构角度考虑选择阻塞队列
- ArrayBlockingQueue:数组的形式。没有链表所需要的“节点”,空间利用率更高。所以如果我们对性能有要求可以从内存的结构角度去考虑这个问题。
- LinkedBlockingQueue:链表的形式。
从性能角度考虑选择阻塞队列
- 比如 LinkedBlockingQueue 由于拥有两把锁,它的操作粒度更细,在并发程度高的时候,相对于只有一把锁的 ArrayBlockingQueue 性能会更好。
- SynchronousQueue 性能往往优于其他实现,因为它只需要“直接传递”,而不需要存储的过程。如果我们的场景需要直接传递的话,可以优先考虑 SynchronousQueue。
结束语
- 获取更多本文的前置知识文章,以及新的有价值的文章,让我们一起成为架构师!
- 关注公众号,可以让你对MySQL有非常深入的了解
- 关注公众号,每天持续高效的了解并发编程!
- 关注公众号,后续持续高效的了解spring源码!
- 这个公众号,无广告!!!每日更新!!!
标签:队列,编程,LinkedBlockingQueue,阻塞,链表,并发,SynchronousQueue,ArrayBlockingQueue 来源: https://www.cnblogs.com/zfcq/p/15863480.html