java基础-集合-ConcurrentHashMap源码学习

文章目录

    • putVal
    • initTable
    • get

putVal

final V putVal(K key, V value, boolean onlyIfAbsent) {// 不允许 key或value 为null,HashMap允许 key 为nullif (key == null || value == null) throw new NullPointerException();// 计算hash,将key的hashCode的高16位和低16位进行异或,增大随机性,HASH_BITS为0x7fffffff,二进制为11111111111111111111111111111111,进行&操作,如果两个都是1则为1,否则为0,这样为1和为0的概率都为百分之五十,这样做也是为了增大hash的随机性,减少hash碰撞的几率int hash = spread(key.hashCode());int binCount = 0;for (Node<K,V>[] tab = table;;) {Node<K,V> f; int n, i, fh; K fk; V fv;// 判断tab是不是空或者tab的长度是否等于0,如果满足条件,则说明数组没有初始化,需要进行数组的初始化if (tab == null || (n = tab.length) == 0)tab = initTable();// 当前数组上的位置的元素为null,则创建一个Node使用CAS操作将元素放到桶中,并且终止循环。else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value)))break;                   // no lock when adding to empty bin}// 当前桶节点正在处于MOVED状态,说明正在扩容,那么就帮助进行扩容。else if ((fh = f.hash) == MOVED)tab = helpTransfer(tab, f);// 需要替换已有值,则替换,否则不替换else if (onlyIfAbsent // check first node without acquiring lock&& fh == hash&& ((fk = f.key) == key || (fk != null && key.equals(fk)))&& (fv = f.val) != null)return fv;else {V oldVal = null;synchronized (f) {if (tabAt(tab, i) == f) {//     static final int MOVED     = -1; // hash for forwarding nodes//	   static final int TREEBIN   = -2; // hash for roots of trees//     static final int RESERVED  = -3; // hash for transient reservations// fh >= 0 此节点为链表结构if (fh >= 0) {binCount = 1;// 循环链表,在尾节点上添加元素,此时binCount在自增,binCount为后续判断是否将链表转为树结构的条件之一for (Node<K,V> e = f;; ++binCount) {K ek;// 新元素待放位置上已有元素if (e.hash == hash &&((ek = e.key) == key ||(ek != null && key.equals(ek)))) {oldVal = e.val;// 需要替换已有值,则替换,否则不替换if (!onlyIfAbsent)e.val = value;break;}Node<K,V> pred = e;// 将新元素添加到尾节点上if ((e = e.next) == null) {pred.next = new Node<K,V>(hash, key, value);break;}}}// 此节点为树结构else if (f instanceof TreeBin) {Node<K,V> p;binCount = 2;// 将元素添加到树节点上,若p != null,说明要放置的的节点上已有值,if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,value)) != null) {oldVal = p.val;// 需要替换已有值,则替换,否则不替换if (!onlyIfAbsent)p.val = value;}}// TODOelse if (f instanceof ReservationNode)throw new IllegalStateException("Recursive update");}}if (binCount != 0) {// 节点元素为链表且链表上元素总数>=8if (binCount >= TREEIFY_THRESHOLD)// 树化tabtreeifyBin(tab, i);if (oldVal != null)return oldVal;break;}}}addCount(1L, binCount);return null;}

initTable

private final Node<K,V>[] initTable() {Node<K,V>[] tab; int sc;// 首先判断table为空时,会对数组进行初始化while ((tab = table) == null || tab.length == 0) {// sizeCtl默认值为0,如果sizeCtl小于0,根据sizeCtl的注释可以得知,说明table正在初始化,如果正在初始化,则当前线程让出CPU执行权,因为只能有一个线程去初始化table。if ((sc = sizeCtl) < 0)Thread.yield(); // lost initialization race; just spin// 如果sizeCtl大于0,则尝试使用CAS进行替换将SIZECTL,替换为-1,如果替换成功,就由当前线程去做table的初始化。else if (U.compareAndSetInt(this, SIZECTL, sc, -1)) {try {// 再次判断table为空时,对数组进行初始化if ((tab = table) == null || tab.length == 0) {// 因为默认sc为0,默认容量为DEFAULT_CAPACITY 16int n = (sc > 0) ? sc : DEFAULT_CAPACITY;@SuppressWarnings("unchecked")Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];table = tab = nt;sc = n - (n >>> 2);}} finally {sizeCtl = sc;}break;}}return tab;}

get

public V get(Object key) {Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;int h = spread(key.hashCode());// table不为空,table.length>0, hash下表桶上有元素if ((tab = table) != null && (n = tab.length) > 0 &&(e = tabAt(tab, (n - 1) & h)) != null) {// 当前桶节点hash值和计算的hash相等,并且key值也相等,则返回对应的value。if ((eh = e.hash) == h) {if ((ek = e.key) == key || (ek != null && key.equals(ek)))return e.val;}// 如果桶节点的hash值小于0,则说明是红黑树,使用TreeNode的find方法,对红黑树的节点进行遍历,直到找到key相等的元素返回对应value。else if (eh < 0)return (p = e.find(h, key)) != null ? p.val : null;// 桶节点下面不是红黑树,说明是一个链表,对链表进行遍历,直到遍历到key相等的元素返回对应value。while ((e = e.next) != null) {if (e.hash == h &&((ek = e.key) == key || (ek != null && key.equals(ek))))return e.val;}}return null;}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/79668.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Stable Diffusion WebUI内存不够爆CUDA Out of memory怎么办?

在我们运行SD的时候,我们经常会爆CUDA Out of memory。 我们应该怎么办呢? 这是因为我们的显存或者内存不够了。 如果你是用cpu来跑图的则表示内存不够,这个时候就需要换个大点的内存了。 如果你是用gpu来跑图的就说明你显存不够用咯,这时候咋办呢? 下面我将一一述说…

Zookeeper运维

我是一个目录 1. 参数说明2. Zookeeper优化建议3. Zookeeper性能查看4. 建议 1. 参数说明 工作节点瞬间压力大&#xff0c;导致和集群通信出现延迟&#xff0c;被踢出节点&#xff0c;瞬间释放的连接立即又连接到另外节点&#xff0c;最终集群挂掉。加了一些延迟配置后&#xf…

华为云创新中心黑湖科技:将智能制造进行到底

编辑&#xff1a;阿冒 设计&#xff1a;沐由 一如去年&#xff0c;第二届828 B2B企业节从8月28日-9月15日期间&#xff0c;再一次成为广大企业界关注的焦点。 当前&#xff0c;数字技术已经被广泛被融入到产品、服务与流程当中&#xff0c;用以转变客户的业务成果&#xff0c;以…

ChatGPT在职业规划中的智能助手

随着科技的不断发展&#xff0c;人工智能&#xff08;AI&#xff09;正逐渐成为我们日常生活的一部分。ChatGPT作为一种智能语言模型&#xff0c;可以在职业规划中充当智能助手的角色。本文将探讨ChatGPT在职业规划中的应用&#xff0c;以及它如何成为未来工作的智能伙伴。 首先…

基于SpringBoot+Vue实现的党校培训管理系统源代码+数据库

一、简介 项目简介&#xff1a; 基于微服务架构的党校培训管理系统&#xff0c; 完整代码下载地址&#xff1a;党校培训管理系统 大体总结&#xff1a; 前端使用Vue.js框架&#xff0c;UI组件库使用Element UI与Ant Design Vue&#xff0c;后端基于Spring Boot&#xff0c;使…

实现客户端pineline的思路

背景&#xff1a; redis集群不支持客户端的mget操作&#xff0c;但是业务上对这个redis集群的批量操作的需求一直都在&#xff0c;所以有各种客户端实现了各式各样的pineline实现,本文就记录下我们公司的实现方式 pineline实现思路 1.pineline要快 pineline之所以快是因为可…

mybatis mapper.xml 文件外键映射

1.业务背景 最近负责标签管理业务&#xff0c;因为设计打标签功能就需要用到中间表。在之前的写法&#xff0c;将符合的数据先查询出来在应用层做匹配封装。如果是大表关联性复杂考虑到之后的扩展性&#xff0c;这种写法符合要求的&#xff0c;唯一缺点就是让你代码看的很臃肿&…

面试算法6:排序数组中的两个数字之和

题目 输入一个递增排序的数组和一个值k&#xff0c;请问如何在数组中找出两个和为k的数字并返回它们的下标&#xff1f;假设数组中存在且只存在一对符合条件的数字&#xff0c;同时一个数字不能使用两次。例如&#xff0c;输入数组[1&#xff0c;2&#xff0c;4&#xff0c;6&…

【华为重启门】华为/荣耀手机一直自动重启原因解决方案(荣耀V10)

文章目录 【目前&#xff1a;系统回退安卓10、CPU贴了硅胶片。一天没重启了】1.问题描述2.分析原因3.解决方案4.实际操作 【目前&#xff1a;系统回退安卓10、CPU贴了硅胶片。一天没重启了】 1.问题描述 荣耀V10&#xff0c;莫名其妙的、无规律的死机重启。 一开始是重启后进…

Ubuntu22.04配置WiFi

Ubuntu22.04配置WiFi 注意&#xff1a;在/etc/netplan/​下的配置文件&#xff0c;格式一定要正确&#xff0c;否则用sudo netplan try​的时候会报错 一、查看无线网卡的名称 //choice-1 ls /sys/class/net//choice-2 ip a//choice-3 ifconfig -a‍ 二、修改配置文件 文件…

jmeter接口测试及详细步骤以及项目实战教程

在接口测试项目实战中&#xff0c;JMeter是一款非常强大和流行的自动化测试工具&#xff0c;它可以测试各种类型的应用程序&#xff0c;并通过采样和报告来识别性能瓶颈和API的问题。本文将为你提供一个基于实际项目的JMeter接口测试项目实战教程&#xff0c;指导你如何使用JMe…

分布式事务解决方案之2PC

分布式事务解决方案之2PC 前面已经学习了分布式事务的基础理论&#xff0c;以理论为基础&#xff0c;针对不同的分布式场景业界常见的解决方案有2PC、 TCC、可靠消息最终一致性、最大努力通知这几种。 什么是2PC 2PC即两阶段提交协议&#xff0c;是将整个事务流程分为两个阶段…

一种新的图像去噪方式:图像修补+斑点检测的预处理

灵感来源于我之前写的一篇博客&#xff1a;图像处理&#xff1a;基于cv2.inpaint()图像修补。 这种方式可以有效的去除白色的噪点&#xff0c;这里我们需要一张噪点的图像&#xff0c;你可以用下面的代码随机生成一张噪点图片&#xff1a; import cv2 import numpy as np # i…

软件设计模式系列之六——单例模式

1 模式的定义 单例模式&#xff08;Singleton Pattern&#xff09;是一种常见的创建型设计模式&#xff0c;其主要目的是确保一个类只有一个实例&#xff0c;并提供一个全局访问点来获取该实例。这意味着无论何时何地&#xff0c;只要需要该类的实例&#xff0c;都会返回同一个…

二刷力扣--栈和队列

栈和队列 栈和队列基础&#xff08;Python&#xff09; 栈一种先进后出&#xff0c;队列先进后出。 Python中可以用list实现栈&#xff0c;用append()模拟入栈&#xff0c;用pop()模拟出栈。 也可以用list实现队列&#xff0c;但是效率较低&#xff0c;一般用collections.deq…

vue2以ElementUI为例构建notify便捷精美提示

我们先引入一个 第三方UI库 这里 我们以elementUI为例 先引入依赖 npm install element-ui --save然后 在 main.js 入口文件中 引入一下 import ElementUI from element-ui import element-ui/lib/theme-chalk/index.cssVue.use(ElementUI)然后 在组件中使用 this.$notify({…

如何使用 RunwayML 进行创意 AI 创作

标题&#xff1a;如何使用 RunwayML 进行创意 AI 创作 介绍 RunwayML 是一个基于浏览器的人工智能创作工具&#xff0c;可让用户使用各种 AI 功能来生成图像、视频、音乐、文字和其他创意内容。RunwayML 的功能包括&#xff1a; * 图像生成&#xff1a;使用生成式对抗网络 (…

每日刷题-6

目录 一、选择题 二、算法题 1.Fibonacci数列 2.合法括号序列判断 一、选择题 1、 解析&#xff1a;内联函数是一种可以提高函数执行效率的方法&#xff0c;它的原理是编译时在函数调用点直接展开函数体的代码&#xff0c;从而避免了函数调用的开销。 但是&#xff0c;内联函…

Haproxy负载均衡集群 超详细 (附部署实例)

Haproxy 一、Web集群调度器1.1 常用的Web集群调度器1.2 常用集群调度器的优缺点&#xff08;LVS ,Nginx,Haproxy)1.2.1 Nginx1.2.2 LVS1.2.3 Haproxy 1.3 LVS、Nginx、Haproxy的区别 二、Haproxy2.1 简介2.2 Haproxy的主要特性2.3 Haproxy应用分析2.4 Haproxy的调度算法(负载均…

uni-app 微信小程序movable-area遮盖 遮挡住 点击事件

问题描述&#xff1a; 使用了movable-area拖拽在页面有点击事件的地方会覆盖住点击事件 直接上代码&#xff1a; <movable-area class"movable-area"><movable-view class"movable-view" :x"x" :y"y" direction"all&q…