HashMap1.8也会发生死循环—记录

news2024/11/20 20:34:48

目录

代码

jstack

分析


什么是哈希表

在讨论哈希表之前,我们先大概了解下其他数据结构在新增,查找等基础操作执行性能

数组:采用一段连续的存储单元来存储数据。对于指定下标的查找,时间复杂度为O(1);通过给定值进行查找,需要遍历数组,逐一比对给定关键字和数组元素,时间复杂度为O(n),当然,对于有序数组,则可采用二分查找,插值查找,斐波那契查找等方式,可将查找复杂度提高为O(logn);对于一般的插入删除操作,涉及到数组元素的移动,其平均复杂度也为O(n)

线性链表:对于链表的新增,删除等操作(在找到指定操作位置后),仅需处理结点间的引用即可,时间复杂度为O(1),而查找操作需要遍历链表逐一进行比对,复杂度为O(n)

二叉树:对一棵相对平衡的有序二叉树,对其进行插入,查找,删除等操作,平均复杂度均为O(logn)。

哈希表:相比上述几种数据结构,在哈希表中进行添加,删除,查找等操作,性能十分之高,不考虑哈希冲突的情况下(后面会探讨下哈希冲突的情况),仅需一次定位即可完成,时间复杂度为O(1),接下来我们就来看看哈希表是如何实现达到惊艳的常数阶O(1)的。

我们知道,数据结构的物理存储结构只有两种:顺序存储结构链式存储结构(像栈,队列,树,图等是从逻辑结构去抽象的,映射到内存中,也这两种物理组织形式),而在上面我们提到过,在数组中根据下标查找某个元素,一次定位就可以达到,哈希表利用了这种特性,哈希表的主干就是数组

比如我们要新增或查找某个元素,我们通过把当前元素的关键字 通过某个函数映射到数组中的某个位置,通过数组下标一次定位就可完成操作。
  
这个函数可以简单描述为:存储位置 = f(关键字) ,这个函数f一般称为哈希函数,这个函数的设计好坏会直接影响到哈希表的优劣。

hashmap在并发执行put操作时会引起死循环,因为在put中会引起扩容操作,使链表形成环形的数据结构,不是很明白,然后在网上看了一些博客,但是博客都是jdk1.7版本的,而1.8版本中的扩容操作已经和1.7版本中大不一样了,于是自己开始研究,看源码的时候,觉得jdk1.8版本中多线程put不会在出现死循环问题了,只有可能出现数据丢失的情况,因为1.8版本中,会将原来的链表结构保存在节点e中,然后依次遍历e,根据hash&n是否等于0,分成两条支链,保存在新数组中。jdk1.7版本中,扩容过程中会新数组会和原来的数组有指针引用关系,所以将引起死循环问题。

jdk1.8的HashMap在多线程的情况下也会出现死循环的问题,但是1.8是在链表转换树或者对树进行操作的时候会出现线程安全的问题。

复习一下线程安全的定义:
在拥有共享数据的多条线程并行执行的程序中,线程安全的代码会通过同步机制保证各个线程都可以正常且正确的执行,不会出现数据污染等意外情况。
 

代码

类名字我忘记改了这是我以前看park时候弄的但是这不重要

当你运行

public class parkAndUnpark {
    static  Map<String,String> map = new HashMap<>();
    static class MyTask implements Runnable{
        int start = 0;
        public MyTask(int start){
            this.start = start;
        }
        @Override
        public void run() {
            for(int i = start ; i<10000000;i+=2){
                map.put(Integer.toString(i),Integer.toBinaryString(i));
                System.out.println(i);
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new MyTask(0));
        Thread t2 = new Thread(new MyTask(1));
        t1.start();
        t2.start();
        //主线程等待两个线程执行完
        t1.join();
        t2.join();
        System.out.println(map.size());
    }
}

好了这里会阻塞住
但是可能你没阻塞住所以多运行几次

实验jps查看运行线程 

jstack

使用jstack分析堆栈快照

 

两个线程都在运行但是没有输出同时也没有结束这就产生了死循环,所以分析

分析

分析balanceInsertion 方法,上面就可以看到

 static <K,V> TreeNode<K,V> balanceInsertion(TreeNode<K,V> root,
                                             TreeNode<K,V> x) {
     //新插入的节点标为红色
     x.red = true;
     
     //无限for循环,定义xp、xpp、xppl、xppr变量,在循环体进行赋值,p就是parents
     //- root:当前根节点
     //- x   :新插入的节点
     //- xp  :新插入节点的父节点
     //- xpp :新插入节点的祖父节点
     //- xppl:新插入节点的左叔叔节点
     //- xppr:新插入节点的右叔叔节点
     for (TreeNode<K,V> xp, xpp, xppl, xppr;;) {
     	 
     	 //为定义的各个变量赋值的过程
         if ((xp = x.parent) == null) {
             x.red = false;
             return x;
         }
         else if (!xp.red || (xpp = xp.parent) == null)
             return root;
         //重点看这里
         //如果父节点是爷爷节点的左孩子
         if (xp == (xppl = xpp.left)) {
         	 //如果右叔叔不为空且为红色
             if ((xppr = xpp.right) != null && xppr.red) {
             	 //右叔叔变为黑色
                 xppr.red = false;
                 //父节点变为黑色
                 xp.red = false;
                 //爷爷节点变为黑色
                 xpp.red = true;
                 //将爷爷节点当作起始节点,再次循环,请注意再次循环!!!
                 x = xpp;
             }
		//省略其他代码
 }

总的来说上边的源码就是,新插入一个节点,该方法要保持红黑树的五个性质

性质1. 节点是红色或黑色。
性质2. 根节点是黑色。
性质3 每个叶节点(NIL节点,空节点)是黑色的。
性质4 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
性质5. 从任一节点到其每个叶子的路径上包含的黑色节点数量都相同。

 

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

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

相关文章

web课程设计网页规划与设计:HTML+CSS美妆设计题材——雅诗兰黛(5页)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

制作移动端整页滚动动画

制作移动端整页滚动动画 需要用到 rem7.5.js(rem适配) pageSlider.js(控制动画的js文件) 基于zepto&#xff0c;引入zepto.js文件 animate.css(动画样式) base.css(公共样式) 下面看一下页面结构 <div class"section sec1"style"background-image:url(./ima…

Java设计模式 - 管道模式

管道模式是责任链模式的常用变种之一&#xff0c;但是管道模式和责任链模式有一个关键的区别&#xff0c;在看一些博客的时候并没有体现出来出来&#xff0c;很多人都把责任链模式当做管道模式来说。 定义 管道模式使用有序的Stage(或者Handler)来顺序的处理一个输入值&#…

以智能视觉驱动智慧出行,看中科创达如何持续深耕汽车市场

当前&#xff0c;360全景环视&#xff08;AVM&#xff09;正在往丰富的ADAS功能、透明底盘功能、不同等级的自动泊车功能等领域拓展&#xff0c;全景环视市场的多元化增长路径已经全面开启。 高工智能汽车研究院监测数据显示&#xff0c;2022年1-9月中国市场&#xff08;不含进…

工厂应该如何批量打印送货单和产品标签

01基本需求 图1是公司的出货明细表&#xff0c;要求按图2的样式批量打印标签&#xff0c;然后将标签张贴在产品包装箱上&#xff0c;否则客户不收货。 其中A7单元格用于存放条形码&#xff0c;条形码用于存放产品的订单号。 图1 订单表 图2 标签模板样式 02操作步骤 利用E…

【2023春招Java岗面试】 90% 会问到的 200+Java 面试题汇总(含答案解析),一定要抓住重点

前言 很多朋友问&#xff0c;有没有整理今年的一些面试题&#xff0c;最近抽时间整理了一份 Java 面试题。或许这份面试题还不足以囊括所有 Java 问题&#xff0c;但有了它&#xff0c;我相信足以应对目前市面上绝大部分的 Java 面试了&#xff0c;因为这篇文章不论是从深度还…

简单讲解Linux PSCI框架

说明&#xff1a; Kernel版本&#xff1a;4.14ARM64处理器使用工具&#xff1a;Source Insight 3.5&#xff0c; Visio 1. 介绍 PSCI, Power State Coordination Interface&#xff0c;由ARM定义的电源管理接口规范&#xff0c;通常由Firmware来实现&#xff0c;而Linux系统可…

014 | 探讨京族民间传说中的海洋文化特质 | 大学生创新训练项目申请书 | 极致技术工厂

&#xff08;一&#xff09;研究目的 京族是我国56个民族中唯一一个生活在海边的少数民族&#xff0c;这一特殊的少数民族位于我国西南沿海边陲&#xff0c;有着独具特色的海洋文化。渔民的海神信仰、特殊的舞蹈和乐器积淀了京族丰富的历史文化。以海洋地域为背景、世世代代以海…

神经网络的应用(分类和预测)——python

神经网络的应用一.数据预处理 ​ 由于神经网络输入数据的范围可能特别大&#xff0c;导致神经网络收敛慢、训练时间长。因此在训练神经网络前一般对数据进行预处理(不妨假设这里的指标都是效益型的(即都是正项指标))&#xff0c;一种重要的预处理的处理手段是归一化处理&#…

CMake中set_property/get_property的使用

CMake中的set_property命令用于在给定作用域(scope)内设置命名属性&#xff0c;其格式如下&#xff1a; set_property(<GLOBAL |DIRECTORY [<dir>] |TARGET [<target1> ...] |SOURCE [<src1> ...][DIRECTORY <…

小程序AP配网和AK配网教程(开源)

小程序AP配网和AK配网教程&#xff08;开源&#xff09; 一、 Airkiss配网的实现方式 ​ Airkiss配网我们采用插件的形式&#xff0c;非常简单方便。感谢半颗心脏大佬的开源插件。 1. Airkiss 简介 AirKiss是微信硬件平台为Wi-Fi设备提供的微信配网、局域网发现和局域网通讯…

将两个数组进行竖直(水平)方向的拼接 vstack()和hstack()

【小白从小学Python、C、Java】 【计算机等级考试500强双证书】 【Python-数据分析】 将两个数组进行竖直(水平)方向的拼接 vstack()和hstack() [太阳]选择题 以下关于Python代码的选项说法错误的一项是? import numpy as np myArray1np.array([1,2,3]) print("【…

主线程与分支线程的访问、修改

任务1&#xff1a;定义一个全局变量 int a10&#xff0c;主线程能否访问到&#xff0c;分支线程能否访问到&#xff1b; 任务2&#xff1a;分支线程中修改上述的a 20, 问主线程中访问该a&#xff0c;是10还是20; 任务3&#xff1a;在主线程定义一个局部变量int b1&#x…

代码随想录刷题day59 503.下一个更大元素II;42. 接雨水

代码随想录刷题day59 503.下一个更大元素II&#xff1b;42. 接雨水 单调栈的一些应用。 503.下一个更大元素II 503. 下一个更大元素 II - 力扣&#xff08;Leetcode&#xff09; 还是下一个最大元素&#xff0c;主要是掌握循环数组中利用%取余的这个操作&#xff0c;在循环…

微服务框架 SpringCloud微服务架构 28 数据同步 28.1 同步方案分析

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构28 数据同步28.1 同步方案分析28.1.1 数据同步问题分析28.1.2 总结28 数据…

Yarn增加新队列-----hive向Yarn提交任务后,Hadoop再次向Yarn提交任务阻塞

博学之&#xff0c;审问之&#xff0c;慎思之&#xff0c;明辨之&#xff0c;笃行之&#x1f3c2; hive on spark搭建好后&#xff0c;任务提交会有问题&#xff0c;因为通过hive会话提交的任务一直存在且不会结束&#xff08;除非关掉这个hive会话&#xff09;&#xff0c;根本…

微服务框架 SpringCloud微服务架构 27 自动补全 27.4 修改酒店索引库数据结构

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构27 自动补全27.4 修改酒店索引库数据结构27.4.1 案例27 自动补全 27.4 修…

Java中的Unsafe的介绍与使用

Java中的Unsafe的介绍与使用 相关文章 美团-Unsafe JavaGuide-Unsafe 什么是Unsafe&#xff1f;&#xff1f;&#xff1f; 如何创建Unsafe对象&#xff1f; 通过反射获取Unsafe对象&#xff08;案例&#xff09; Unsafe功能简介 1. 内存操作 2. 内存屏障 3. 对象操…

猿如意中的【Sublime Text】开发工具详情介绍

目录 一、工具名称 二、下载安装渠道 2.1 什么是猿如意&#xff1f; 2.2 如何下载猿如意&#xff1f; 2.3 如何在猿如意中下载Sublime Text &#xff1f; 三、sublime text介绍 四、软件安装过程 五、软件界面 六、sublime text功能特点介绍 七、sublime tex…

【UDS】ISO15765-2之协议数据单元

文章目录简介结构格式分类1.单帧SF2.首帧FF3.流控帧FC4.连续帧CF总结->返回总目录<- 简介 网络层协议数据单元&#xff08;N_PDU&#xff0c;Network_Protocol Data Unit&#xff09;。可以理解成是一种规范协议。而汽车电子中通信的报文格式就是以PDU为传输单元&#…