范文健康探索娱乐情感热点
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文

Java多线程下用HashMap要注意了

  Java的HashMap是非线程安全的。多线程下应该用ConcurrentHashMap。
  多线程下[HashMap]的问题(这里主要说死循环问题):  多线程put操作后,get操作导致死循环。  多线程put非NULL元素后,get操作得到NULL值。  多线程put操作,导致元素丢失。  1、为何出现死循环?(在多线程下使用非线程安全的HashMap,单线程根本不会出现)HashMap是采用链表解决Hash冲突,因为是链表结构,那么就很容易形成闭合的链路,这样在循环的时候只要有线程对这个HashMap进行get操作就会产生死循环。  在单线程情况下,只有一个线程对HashMap的数据结构进行操作,是不可能产生闭合的回路的。  那就只有在多线程并发的情况下才会出现这种情况,那就是在put操作的时候,如果 size>initialCapacity*loadFactor ,那么这时候HashMap就会进行rehash操作,随之HashMap的结构就会发生翻天覆地的变化。很有可能就是在两个线程在这个时候同时触发了rehash操作,产生了闭合的回路。 2、如何产生的:
  存储数据 put() :  public V put(K key, V value)  {   ......   //算Hash值   int hash = hash(key.hashCode());   int i = indexFor(hash, table.length);   //如果该key已被插入,则替换掉旧的value (链接操作)   for (Entry e = table[i]; e != null; e = e.next) {    Object k;    if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {     V oldValue = e.value;     e.value = value;     e.recordAccess(this);     return oldValue;    }   }   modCount++;   //该key不存在,需要增加一个结点   addEntry(hash, key, value, i);   return null;  } 
  当我们往HashMap中put元素的时候,先根据key的hash值得到这个元素在数组中的位置(即下标),然后就可以把这个元素放到对应的位置中了。
  如果这个元素所在的位置上已经存放有其他元素了,那么在同一个位子上的元素将以链表的形式存放,新加入的元素放在链头,而先前加入的放在链尾。
  检查容量是否超标addEntry:   void addEntry(int hash, K key, V value, int bucketIndex)  {   Entry e = table[bucketIndex];   table[bucketIndex] = new Entry(hash, key, value, e);   //查看当前的size是否超过了我们设定的阈值threshold,如果超过,需要resize   if (size++ >= threshold)    resize(2 * table.length);  } 
  如果现在size已经超过了threshold,那么就要进行resize操作,新建一个更大尺寸的hash表,然后把数据从老的Hash表中迁移到新的Hash表中。
  调整Hash表大小resize:   void resize(int newCapacity)  {   Entry[] oldTable = table;   int oldCapacity = oldTable.length;   ......   //创建一个新的Hash Table   Entry[] newTable = new Entry[newCapacity];   //将Old Hash Table上的数据迁移到New Hash Table上   transfer(newTable);   table = newTable;   threshold = (int)(newCapacity * loadFactor);  }
  当table[]数组容量较小,容易产生哈希碰撞,所以,Hash表的尺寸和容量非常的重要。
  一般来说,Hash表这个容器当有数据要插入时,都会检查容量有没有超过设定的thredhold,如果超过,需要增大Hash表的尺寸,这个过程称为resize。
  多个线程同时往HashMap添加新元素时,多次resize会有一定概率出现死循环,因为每次resize需要把旧的数据映射到新的哈希表,这一部分代码在 HashMap#transfer()  方法,如下:  void transfer(Entry[] newTable)  {   Entry[] src = table;   int newCapacity = newTable.length;   //下面这段代码的意思是:   //  从OldTable里摘一个元素出来,然后放到NewTable中   for (int j = 0; j < src.length; j++) {    Entry e = src[j];    if (e != null) {     src[j] = null;     do {      Entry next = e.next;//取出第一个元素      int i = indexFor(e.hash, newCapacity);      e.next = newTable[i];      newTable[i] = e;      e = next;     } while (e != null);    }   }  } 
  标红代码是导致多线程使用hashmap出现CUP使用率骤增,出现死循环,从而多个线程阻塞的罪魁祸首。另外推荐:Java进阶视频资源  3、图解HashMap死循环:
  正常的ReHash的过程(单线程):假设了我们的hash算法就是简单的用key mod 一下表的大小(也就是数组的长度)。
  最上面的是old hash 表,其中的Hash表的size=2, 所以 key = 3, 7, 5 ,在mod 2以后都冲突在table[1] 这里了。接下来的三个步骤是Hash表 resize成4,然后所有的  重新rehash的过程。
  并发下的Rehash(多线程)
  1)假设我们有两个线程。   do {   Entry next = e.next; // <--假设线程一执行到这里就被调度挂起了,执行其他操作   int i = indexFor(e.hash, newCapacity);   e.next = newTable[i];   newTable[i] = e;   e = next;  } while (e != null); 
  而我们的线程二执行完成了。于是我们有下面的这个样子:
  注意,因为Thread1的 e 指向了key(3),而next指向了key(7),其在线程二rehash后,指向了线程二重组后的链表。我们可以看到链表的顺序被反转后。在这里线程一变成了操作经过线程二操作后的HashMap。
  2)线程一被调度回来执行。  先是执行  newTalbe[i] = e;  然后是 e = next ,导致了e指向了key(7) , 而下一次循环的 next = e.next 导致了next指向了key(3) 。
  3)一切安好。
  线程一接着工作。把 key(7) 摘下来,放到newTable[i] 的第一个,然后把e和next往下移。这个元素所在的位置上已经存放有其他元素了,那么在同一个位子上的元素将以链表的形式存放,新加入的放在链头,而先前加入的放在链尾。
  4)环形链接出现。
  e.next = newTable[i]  导致 key(3).next  指向了 key(7) 。
  注意:此时的  key(7).next   已经指向了 key(3)  , 环形链表就这样出现了。
  于是,当我们的线程一调用到, HashTable.get(11) 时,悲剧就出现了——Infinite Loop。
  这里介绍了在多线程下为什么HashMap会出现死循环,不过在真实的生产环境下,不会使用线程不安全的HashMap的。
  来源:https://juejin.cn/post/7003321088386170893

热血传奇战士最重要的武器,搭配也是十分重要的在传奇这款游戏中战士这个职业是开销最大的职业,装备要比其他两个职业贵上不少,而且就连维修都要高出一大截。而且战士最为重要的便是武器了,一个高级的战士武器轻轻松松就能卖出高价。在游戏王者荣耀新赛季7月9日正式开启,你想知道的都在这里王者荣耀S20赛季将在明天,也就是7月9日正式开启。打上最强王者段位的小伙伴可能早就翘首以盼了,而还在星耀段位沉浮的兄弟大概率要熬夜冲分了。新赛季有哪些值得期待的变化呢,峡谷妖刀带复古传奇828万人堵门事件,盛大官方却对这些玩家进行镇压传奇可以说是国内网游界的开山鼻祖,出道即是巅峰,他是70,80后玩家的回忆,他已经不再是一款游戏,而是一代人的青春一代人的回忆,今天就为大家讲述一下传奇著名事件828万人堵门事件。热血传奇19年过去了,回顾过去的成长之路,不愧是热血传奇哈喽大家好,热血传奇从2001年到现在不经意间已经19年了,爆火的程度也比不上当初了,但回顾过去的成长之路,这不禁让人感慨热血传奇不愧是热血传奇。典型的传说是刚开始公测的时候,一群热血传奇打金的重要性?该如何打金?打金需要注意什么?哈喽大家好,很多传奇的老玩家应该都知道打金这个词,通过爆出高级和稀有的装备跟游戏内有钱的大佬进行交易,然后获得自己想要的东西以前古传奇是没有什么商铺的,开局就是一把刀,装备全靠打出热血传奇这些装备被称为逆天装备的都具备哪些条件呢?热血传奇中装备被称为逆天装备的都具备哪些条件呢?我觉得不管装备有多稀有,只要是玩家手动打出的或者加上幸运所获得的最佳属性,都不能称之为逆天装备,那么这些逆天装备都有哪些呢?下面我就黄刀宝石流套路火了,让你上分如喝水前两天写了一个边路食人鱼的攻略,有朋友留言日暮反甲暴烈冰心魔女,而且不止一个人留言。于是今天早上打了两把,测试了一下这套出装。同时,一并把最近大火的黄刀宝石流一起测试了一下,还不知热血传奇你见过哪些传奇里的地图关于传奇中存在的一些死门,大家基本上都是见过的,比如封魔殿里的,又比如牛七右边的门,牛八最左自然洞穴下方的门,以及沃玛森林中的两条路,尤其是沃玛森林中的一条路后来还真的开通了,直接热血传奇义战龙城,快速起步,人人当大佬今天来和大家聊一款传奇手游,这款传奇其实已经推出一段时间了,同样我也玩了一段时间,今天就和大家分享一下。进游戏选择完角色之后跟着任务走会送一个首曝boss,看个人运气,然后可以选择冰雪合击手游冰雪合击,还不知道选择玩什么传奇组合大家好,传奇手游那么多今天小编就来跟大家聊聊作为三职业最受欢迎的游戏冰雪合击,还不知道选择玩什么传奇手游的小伙伴们快来和我一起来了解体验吧!冰雪合击相对于一般的合击游戏,冰雪合击的万血流貂蝉,我要打5个在王者荣耀游戏中,貂蝉是一名非常秀的英雄,会玩的貂蝉能秀到你头皮发麻。那么,你有没有发现在游戏中我们经常会碰到这样一种貂蝉,又肉又有输出,黏住你让你想跑都跑不了,想打又打不过?今天
云顶11。24变异战士阵容破蛹之变弑神大虫子在云顶之弈11。24版本中,变异战士羁绊每局都会出现不同的属性,其中破蛹之变变异效果类似与原来的永恒之森,每过2秒就会提升双抗攻击力和法术强度,最多可叠加5次。5变异战士的破蛹之变热血传奇这么多年过去了,还有多少老玩家还在坚持着传奇从01年至今,经历了很多版本的更新,每次的更新无非就是拼凑地图,虽然是这样但是完全不影响玩家高昂的激情。随着时代的改变,如今的传奇变的快餐化。众多传奇的版本中,1。76版是呼声三国杀十周年刘备儿子刘永爆料,继承刘备仁德的超强辅助三国杀十周年刘备儿子刘永爆料,继承刘备仁德的超强辅助!三国杀移动版最近新杀爆料了许多武将,其中有一个便是刘备与吴苋的儿子刘永,这也是刘备三个亲生儿子其中之一。那么,刘永的强度如何呢2022LPL春季赛常规赛赛程正式公布揭幕战OMG对战TTIT之家12月31日消息,英雄联盟赛事官方微博,2022LPL春季赛常规赛赛程正式公布,17支蓄势待发的战队再次站在同一起跑线上,为银龙冠军奖杯冲刺,无畏竞巅峰!据介绍,1月10日哈利波特手游新时装马上上线!预先get一波绝美搭配?明天就是元旦了!哈利波特魔法觉醒也会在2022年1月1日迎来版本更新,这也意味着,在体验服一上线就获得了超高关注度和超高好评的雪国归客直售套装,和哈利波特与火焰杯电影同款的转盘时装魔药解析即将正式上线?四大阶层的挑战,会逐步向上提升难度最近原神的2。4版本,也是马上就要来了,而通过之前官方发布的直播前瞻,相信玩家们对里面的内容,都有了一定的了解。不得不说,真不愧是过年活动,手笔非常给力,除了四位五星角色外,还有不原神剧情篇9异世界的救世主埃洛伊战胜了哈迪斯的勇者你好,这里是Holdon2099的原神专题。你好,这里是Holdon2099的原神剧情专题。原神的故事是游戏最大的魅力之一,每个角色都有着丰富的背景设定,欢欢是按照自己获取角色的顺寒霜流夏侯惇火了,75减速让敌人缴械,铭文出装是关键在王者荣耀中,夏侯惇是众多坦克战士中最完美的一个,夏侯惇集合了大部分战士的优秀属性,比如灵活的位移,强力的控制,高额的输出,此外,夏侯自身还拥有白起牛魔项羽般的坦度,以及堪比程咬金灵山区前景是?QQ西游运营12年之久2021荣获金翎奖十大最受欢迎网游天命西游(原QQ西游),现在注册即可领取新手成长大礼包!快来畅游西游吧西游记是中国神魔小说的经典之作,达到了古代长篇浪漫主义小说的巅峰,与三国演义DNF盘古开天一斧,47秒竞速强者之路,拿下预赛第一名DNF盘古开天一斧,47秒竞速强者之路,拿下预赛第一名DNF第四届国服巅峰竞速赛,12。1912。28一阶段预赛落下帷幕,50支队伍进入12。311。06二阶段淘汰赛,在预赛中,多开个帖子记账今天3号了,补发上两天的消费情况1月1日元旦买菜加打车23买药12。8啤酒25奶糕10老公给的红包88总支出70,收入882日,没出门,零消费3日,安装网线288老公红包6网购12