java并发编程JUC第四篇:LinkedBlockingQueue

原创
2021/03/25 07:39
阅读数 53

在之前的文章中已经为大家介绍了java并发编程的工具:BlockingQueue接口、ArrayBlockingQueue、DelayQueue。

LinkedBlockingQueue 队列是BlockingQueue接口的实现类,所以它具有BlockingQueue接口的一切功能特点。LinkedBlockingQueue队列 按照first-in-first-out (FIFO)先进先出的方式对元素进行排序。LinkeBlockingQueue 提供了两种构造函数,一个构造函数构造一个队列容量为固定个数的队列,另一个无参构造函数构造一个队列容量为Integer.MAX_VALUE的队列.

public LinkedBlockingQueue() {
    this(Integer.MAX_VALUE);
}

public LinkedBlockingQueue(int capacity) {
    if (capacity <= 0) throw new IllegalArgumentException();
    this.capacity = capacity;
    last = head = new Node<E>(null);
}

ArrayBlockingQueue和LinkedBlockingQueue对比

  • ArrayBlockingQueueLinkedBlockingQueue都是实现BlockingQueue接口,所以在使用方式上是一致的,下面我们就不介绍使用方法,而是从二者的性能及底层数据结构的实现角度进行

  • ArrayBlockingQueue插入和删除数据,只采用了一个lock锁,读取和写入操作无法并行。 所以在高并发场景下执行效率会比LinkedBlockingQueue慢一些。
  • LinkedBlockingQueue采用“two lock queue”算法变体,双锁(ReentrantLock):takeLock、putLock,允许读写并行,remove(e)和迭代器iterators需要获取2个锁。这样可以降低线程由于线程无法获取到lock而进入WAITING状态的可能性,从而提高了线程并发执行的效率。

  • ArrayBlockingQueue底层代码是采用数组实现的,创建的时候必须指定队列的容量并分配存储空间;LinkedBlockingQueue采用的是链表数据结构实现的,其链表节点的存储空间分配是动态的,新的元素对象加入队列分配空间,元素对象从队列取出之后存储空间GC,初始化时指定的是队列的最大容量。但是使用链表数据结构既是LinkedBlockingQueue优势也是它的劣势,高并发场景下由于空间动态分配需要java JVM频繁的进行垃圾回收。

总体来说在并发场景下,LinkedBlockingQueue的吞吐量比ArrayBlockingQueue更好。但是在java实现高性能队列的首选是disruptor,它不是JDK自带的。java程序员非常熟悉的Log4j2底层性能比logback和log4j有了较大的提升,究其原因就是使用了disruptor高性能队列实现的异步日志


本文分享自微信公众号 - 字母哥课堂(zimug_blog)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

展开阅读全文
加载中

作者的其它热门文章

打赏
0
0 收藏
分享
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部