千家信息网

如何进行阻塞队列LinkedBlockingQueue源码学习与对比

发表于:2025-02-04 作者:千家信息网编辑
千家信息网最后更新 2025年02月04日,这篇文章给大家介绍如何进行阻塞队列LinkedBlockingQueue源码学习与对比,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。今天学习LinkedBlockingQueue
千家信息网最后更新 2025年02月04日如何进行阻塞队列LinkedBlockingQueue源码学习与对比

这篇文章给大家介绍如何进行阻塞队列LinkedBlockingQueue源码学习与对比,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

今天学习LinkedBlockingQueue源码并与之对比。

LinkedBlockingQueue总结

同样先直接总结LinkedBlockingQueue相关的特性,再根据源码来进行说明,它的主要特性如下:

1、他底层用链表实现数据存储;

2、他是一个FIFO无界阻塞队列。数据最大长度默认Intenger的最大值Integer.MAX_VALUE,也可以设置长度;

重要属性介绍

主要属性如下图:

LinkedBlockingQueue有一个内部类Node,用来组成它存储数据的链表,Node的item数据用来存储数据,next表示下一个节点,尾节点的next是null。

capacity容量表示队列最多可存储的数据量,初始化的时候设置,默认是Integer.MAX_VALUE;

count表示当前存储数据的数量,它是AtomicInteger类型(可以想想为什么?);

head链表的头节点,它的item不存放数据;

tail链表的尾节点,它的next为null,也就是没有下一个节点;

takeLock与notEmpty控制take方法的阻塞;

putLock与notFull控制put方法的阻塞;

从上面属性可以猜出来LinkedBlockingQueue是用两个锁来控制数据的读和写,相当于把读和写分开,可以同时存在读和写操作,所以count有可能同时存在多个线程修改,有线程安全问题所以用AtomicInteger

最关键的两个私有方法

同样LinkedBlockingQueue也有两个相同的关键方法,具体代码和解释如下图:

LinkedBlockingQueue的enqueue和dequeue方法比ArrayBlockingQueue的更加简单;

enqueue方法就是把新的节点放到last的next,然后把节点设置成尾节点。

dequeue是先拿到头节点next节点作为first节点,然后之前的头节点就的next设置成了自己,就脱离了链表,下次GC就会被回收掉。

然后first就作为head,把item拿出来后设置为null,所以头节点是不存储数据的,并且是由下一个节点升级来的

LinkedBlockingQueue的这两个方法比较简单,但是也可以看出它实现了FIFO先进先出

主要方法介绍

LinkedBlockingQueue与ArrayBlockingQueue一样都是继承至 AbstractQueue并实现 BlockingQueue接口,所以他们提供的方法都差不多,功能也类似,主要实现不同,上一篇已经详细讲了,这里就只看一下take和put方法的实现。

put方法源码如下图:

一共分四步:

把数据封装成Node节点,获取put锁;

验证队列是否已满,满则阻塞线程;

如果没有满则把节点加到队列中,count加1,并获取加之前的数量;

如果现在数量还是小于最大容量则唤醒阻塞的put线程,如果之前数量是0则唤醒take线程;

take方法源码如下图:

take方法和put方法差不多,主要分以下四步:

首先获取take锁;

判断队列中是否有数据,如果没有则阻塞线程;

调用dequeue方法获取数据,并把count减1;

如果获取前队列数量大于1则说明还有数据,可以唤醒其他take线程,如果获取前队列数量等于最大容器数量则说明有可能有阻塞的put线程,需要唤醒;

可以看到put和take方法很简单,都是先获取到对于的锁,然后根据队列数量判断是否阻塞,然后再添加或者获取数据,最后根据唤醒对应线程

与ArrayBlockingQueue对比(重点)

LinkedBlockingQueue与ArrayBlockingQueue是非常相似的类,通过对比能够更体现他们的优缺点,主要对比如下:

从基础属性对比LinkedBlockingQueue底层实现是链表,ArrayBlockingQueue是数组。ArrayBlockingQueue初始化需要一个数组,而LinkedBlockingQueue是动态数量的Node对象;所以ArrayBlockingQueue需要预先分配内存,而LinkedBlockingQueue不用,如果预计需要缓存的数据很多的,那么ArrayBlockingQueue一开始就需要很大一块数据

但是ArrayBlockingQueue添加元素更快,因为它只是要要保存的对象的引用放到数组对应位置,而LinkedBlockingQueue需要创建一个Node对象;同时在获取后这个Node对象变成了垃圾,在读写很大的情况会多出很多垃圾,可能会影响程序的性能;

ArrayBlockingQueue用一个锁控制读写,LinkedBlockingQueue用两个锁分别控制读写。因为ArrayBlockingQueue为了避免数据被覆盖,而LinkedBlockingQueue不用担心这种情况,可以同时支持读写,而ArrayBlockingQueue同一时刻支持一个操作,所以LinkedBlockingQueue吞吐量更高。

所以ArrayBlockingQueue会占用固定的内存,所以不能支持太大的缓存,但是每次操作延迟更加低,而LinkedBlockingQueue不用暂用一个初始化的内存,但是每次操作消耗的内存更大,不过同时支持读写所以吞吐量更高

但是在使用LinkedBlockingQueue时,如果使用默认大小且当生产速度大于消费速度时候,有可能会内存溢出。

LinkedBlockingQueue与ArrayBlockingQueue提供的功能完全相同,但是他们底层的实现不同,所以侧重点不同,在使用中可以根据情况选择。

关于如何进行阻塞队列LinkedBlockingQueue源码学习与对比就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

数据 方法 节点 队列 阻塞 数量 线程 源码 存储 两个 内存 同时 控制 最大 对象 属性 支持 学习 不同 不用 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 魔兽世界服务器国王之谷 玩gta经常显示服务器无法保存 软件开发总监职位说明书 网络技术革新周期 阿里巴巴数据库世界第一知乎 测绘编程软件开发是什么 苏州应用软件开发流程 广州市夏商舟网络技术 网络安全审查办公室设在哪 数据库结构 展示系统 用数据库创建成绩表 数据库字段唯一约束性 使用家用网络搭建服务器违法吗 手机之间如何传输数据库 云数据库加速 湖南质量软件开发报价表 我的世界1.17版本服务器怎么添加 如何设置服务器 ftp 个人网店需要数据库吗 天玑科技阿里数据库 武汉学习网络安全人才缺口大 莱山区定制软件开发外包公司 甲骨文的数据库开发工作收入 濮阳软件开发电话 数据库如何查询一笔数据 风投北京互联网科技有限公司 面试软件开发如何自我介绍 深高顾研究软件开发 网络安全事故限制上市 网络安全宣传的教育活动
0