一、PriorityBlockingQueue 的put方法底层源码

PriorityBlockingQueue 的 put 方法用于将元素插入队列。由于 PriorityBlockingQueue 是一个无界队列,put 方法不会阻塞,总是会成功插入元素

1、put 方法的作用

  • 将元素插入队列。

  • 由于队列无界,put 方法不会阻塞,总是会成功插入元素。

  • 插入后,队列会根据元素的优先级重新排序。

2、put 方法的源码

以下是 PriorityBlockingQueue 中 put 方法的源码(基于 JDK 17):

可以看到,put 方法直接调用了 offer 方法。因此,我们需要进一步分析 offer 方法的实现。

3、offer 方法的源码

以下是 PriorityBlockingQueue 中 offer 方法的源码:

4、源码解析

(1)参数检查

  • PriorityBlockingQueue 不允许插入 null 元素,如果传入 null,会抛出 NullPointerException。

(2)获取锁

  • lock 是 PriorityBlockingQueue 的成员变量,用于控制插入和移除操作的并发访问。

  • 调用 lock() 方法获取锁。

(3)检查队列容量

  • size 是当前队列中的元素数量。

  • 如果队列已满(n >= queue.length),调用 grow() 方法扩容。

  • grow() 方法的实现:

(4)插入元素并调整堆结构

  • siftUp 方法将元素插入堆中,并调整堆结构以维持堆的性质:

siftUp 方法通过比较元素和其父节点,将元素插入到正确的位置,以维持堆的性质(最小堆或最大堆)

(5)更新队列大小

  • 将队列大小加 1。

(6)唤醒消费者线程

  • 如果队列之前为空,调用 notEmpty.signal() 唤醒可能正在等待的消费者线程。

(7)释放锁

  • 在 finally 块中释放锁,确保锁一定会被释放,避免死锁。

(8)返回结果

  • 由于队列无界,offer 方法总是返回 true。

二、关键点总结

  • 无界队列:PriorityBlockingQueue 是无界队列,put 方法不会阻塞。

  • 堆结构:使用堆数据结构维护元素的优先级顺序。

  • 线程安全:通过 ReentrantLock 保证线程安全。

  • 动态扩容:当队列容量不足时,会自动扩容。

三、示例流程图

以下是 put 方法的执行流程图:

1、检查元素是否为 null。

2、获取锁。

3、检查队列容量,如果不足则扩容。

4、将元素插入堆中,并调整堆结构。

5、更新队列大小。

6、如果队列之前为空,唤醒消费者线程。

7、释放锁。

8、返回 true。

PriorityBlockingQueue 的put方法底层源码的更多相关文章

  1. Android开发之漫漫长途 Ⅵ——图解Android事件分发机制(深入底层源码)

    该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...

  2. 为什么很多类甚者底层源码要implements Serializable ?

    为什么很多类甚者底层源码要implements Serializable ? 在碰到异常类RuntimeException时,发现Throwable实现了 Serializable,还有我们平进的ja ...

  3. List-LinkedList、set集合基础增强底层源码分析

    List-LinkedList 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 继上一章继续讲解,上章内容: List-ArreyLlist集合基础增强底层源码分析:https:// ...

  4. 从底层源码浅析Mybatis的SqlSessionFactory初始化过程

    目录 搭建源码环境 POM依赖 测试SQL Mybatis全局配置文件 UserMapper接口 UserMapper配置 User实体 Main方法 快速进入Debug跟踪 源码分析准备 源码分析 ...

  5. Java泛型底层源码解析-ArrayList,LinkedList,HashSet和HashMap

    声明:以下源代码使用的都是基于JDK1.8_112版本 1. ArrayList源码解析 <1. 集合中存放的依然是对象的引用而不是对象本身,且无法放置原生数据类型,我们需要使用原生数据类型的包 ...

  6. 2018.11.20 Struts2中对结果处理方式分析&struts2内置的方式底层源码剖析

    介绍一下struts2内置帮我们封装好的处理结果方式也就是底层源码分析 这是我们的jar包里面找的位置目录 打开往下拉看到result-type节点 name那一列就是我们的type类型取值 上一篇博 ...

  7. HashMap和ConcurrentHashMap的区别,HashMap的底层源码

    HashMap本质是数组加链表,根据key取得hash值,然后计算出数组下标,如果多个key对应到同一个下标,就用链表串起来,新插入的在前面. ConcurrentHashMap在HashMap的基础 ...

  8. 总结HashSet以及分析部分底层源码

    总结HashSet以及分析部分底层源码 1. HashSet继承的抽象类和实现的接口 继承的抽象类:AbstractSet 实现了Set接口 实现了Cloneable接口 实现了Serializabl ...

  9. LInkedList总结及部分底层源码分析

    LInkedList总结及部分底层源码分析 1. LinkedList的实现与继承关系 继承:AbstractSequentialList 抽象类 实现:List 接口 实现:Deque 接口 实现: ...

  10. Vector总结及部分底层源码分析

    Vector总结及部分底层源码分析 1. Vector继承的抽象类和实现的接口 Vector类实现的接口 List接口:里面定义了List集合的基本接口,Vector进行了实现 RandomAcces ...

随机推荐

  1. Kubernetes 知识梳理及集群搭建

    Kubernetes介绍 应用部署方式演变 在部署应用程序的方式上,主要经历了三个时代: 传统部署:互联网早期,会直接将应用程序部署在物理机上 优点:简单,不需要其它技术的参与 缺点:不能为应用程序定 ...

  2. CentOS扩容boot分区并升级内核

    本文作者CVE-柠檬i:https://www.cnblogs.com/CVE-Lemon 前言 由于安装k8s需要升级内核,但我自己的的boot分区只有200M大小,无法安装新内核,所以干脆把swa ...

  3. 最大流问题:增广路与 Edmonds-Karp 算法

    最大流问题是其中一个经典的图论问题,其目标是在一个流网络中计算从源点到汇点的最大流量.流网络由节点和边组成,每条边都有一个容量,表示该边所能承载的最大流量. 最大流问题 通常来说,最大流问题仅在有向图 ...

  4. JavaScript 中的组合继承 :ES5 与 ES6 中最近似的写法

    JavaScript 的继承写法较多,在此并不一一讨论,仅对最常用的组合式继承做一个说明: 组合式继承主要利用了原型链继承和构造函数继承. 一.ES5 中的写法 function Person(nam ...

  5. 两个半成品的ORM

    只要是有点结构化的思想,不可能项目里一个sqlHelper 满天飞 到处写 ,最终你的c#代码还是得返回一个Class 才好操作,sqlhelper, datatable这种东西也只是临时将就一下,稍 ...

  6. 玩转云端|天翼云边缘安全加速平台AccessOne实用窍门之让办公访问安全、高效又稳定

    本文分享自天翼云开发者社区<玩转云端|天翼云边缘安全加速平台AccessOne实用窍门之让办公访问安全.高效又稳定>,作者:天翼云社区官方账号 随着社会信息化程度不断提高,远程办公已经成为 ...

  7. jar包启停shell脚本

    jar包控制脚本1 #!/bin/bash export JAVA_HOME=/u01/java_home/jdk1.8.0_181 export APP_HOME=/u01/test export ...

  8. MySQL8.0事务知识点

    mysql8.0事务学习 1.基本概念 事务(Transaction)是访问和更新数据库的程序执行单元:是一个最小的不可分割的工作单元,能保证一个业务的完整性:事务中可能包含一个或多个sql语句,这些 ...

  9. lxl-北京总结

    这是 lxl 讲课的总结. lxl lxl 讲课水平很高,相较之下,刚高中毕业以及毕业三年的集训队选手讲课水平不佳. 北京时候: 树上问题:学了点分治和 Boruvka,补了若干奇怪题. DP:学了 ...

  10. [SCOI2007] 蜥蜴 题解

    发现实际上就是在求有多少只蜥蜴能逃出来. 发现可以将柱子拆成入点和出点两部分,自己的出点向别人的入点连边,自己的入点向自己的出点连边.最后再加一个超级源点 \(S\),连接所有有蜥蜴的柱子入点:再加一 ...