【并发容器】4 阻塞/非阻塞队列的介绍与选择
程序员文章站
2022-04-03 09:53:55
阻塞队列是具有阻塞功能的队列,通常一端放入生产者数据,另一端供消费者消费数据。==阻塞队列是线程安全的。==...
4 阻塞/非阻塞队列
阻塞队列是具有阻塞功能的队列,通常一端放入生产者数据,另一端供消费者消费数据。阻塞队列是线程安全的。
阻塞队列,我们主要关注阻塞方法(put/take)、是否有界、与线程池关系。
BlockingQueue的三组方法
- put,take :会阻塞住
- add,remove,element:会抛出异常
- offer,poll,peek:会返回boolean值,取值是没有值会返回null
4.1 常见的阻塞队列
1 ArrayBlockingQueue 有界阻塞队列
ArrayBlockingQueue的特点是有界、可以指定容量、能够指定是否需要保证公平。
put方法源码
public void put(E e) throws InterruptedException {
checkNotNull(e);
final ReentrantLock lock = this.lock;
lock.lockInterruptibly();
try {
while (count == items.length)
notFull.await();
enqueue(e);
} finally {
lock.unlock();
}
}
2 LinkedBlockingQueue
特点是*、默认容量是Integer.MAX_VALUE、内部结构(Node、有两把锁)。
public void put(E e) throws InterruptedException {
if (e == null) throw new NullPointerException();
int c = -1;
Node<E> node = new Node<E>(e);
final ReentrantLock putLock = this.putLock;
final AtomicInteger count = this.count;
putLock.lockInterruptibly();
try {
while (count.get() == capacity) {
notFull.await();
}
enqueue(node);
c = count.getAndIncrement();
if (c + 1 < capacity)
notFull.signal();
} finally {
putLock.unlock();
}
if (c == 0)
signalNotEmpty();
}
3 PriorityBlockingQueue:支持优先级、自然顺序、*队列
4 SynchronousQueue
特点:容量为0,队列不持有元素,直接传递,效率很高。是很好的用来直接传递的并发数据结构。
5 DelayQueue 延迟队列,根据延迟时间排序
4.2 非阻塞队列
并发包中非阻塞队列只有ConcurrentLinkedQueue,以链表作为数据结构,采用CAS思想实现线程安全,适用于对性能要求较高的并发场景。使用较少。源码参考offer方法。
4.3 阻塞队列的选择
选择队列,需要根据实际场景选择。
- 首先考虑功能方面,例如需要优先级排序、延迟执行等。
- 再就是容量,是容量固定,还是*,还是不需要容量。ArrayBlockingQueue不能扩容。
- 内存结构:例如ArrayBlockingQueue底层是数组,而LinkedBlockingQueue内部用链表实现,会生成很多node。
- 吞吐量:LinkedBlockingQueue 由于拥有两把锁,它的操作粒度更细,在并发程度高的时候,相对于只有一把锁的 ArrayBlockingQueue 性能会更好。SynchronousQueue直接传递,性能往往优于其他实现。
本文地址:https://blog.csdn.net/LIZHONGPING00/article/details/114298441