当前位置: 首页 > news >正文

兰州网站建设人才招聘无锡 学校网站建设

兰州网站建设人才招聘,无锡 学校网站建设,电商网站建设价格低,建立网站的英文怎么说转载自 HashMap在java并发中如何发生死循环 在多线程环境中#xff0c;使用HashMap进行put操作时会引起死循环#xff0c;导致CPU使用接近100%#xff0c;下面通过代码分析一下为什么会发生死循环。 首先先分析一下HashMap的数据结构#xff1a;HashMap底层数据结构是有一…转载自   HashMap在java并发中如何发生死循环 在多线程环境中使用HashMap进行put操作时会引起死循环导致CPU使用接近100%下面通过代码分析一下为什么会发生死循环。 首先先分析一下HashMap的数据结构HashMap底层数据结构是有一个链表数据构成的HashMap中定义了一个静态内部类作为链表代码如下与本文无关的代码省略 静态内部类entry代码  static class EntryK,V implements Map.EntryK,V {          final K key;          V value;          EntryK,V next;          final int hash;            /**           * Creates new entry.           */          Entry(int h, K k, V v, EntryK,V n) {              value  v;              next  n;              key  k;              hash  h;          }  、      }  Hashmap属性代码  /**   * The table, resized as necessary. Length MUST Always be a power of two.   */  transient Entry[] table;  之所以会导致HashMap出现死循环是因为多线程会导致HashMap的Entry节点形成环链这样当遍历集合时Entry的next节点用于不为空从而形成死循环 单添加元素时会通过key的hash值确认链表数组下标 public V put(K key, V value) {      if (key  null)          return putForNullKey(value);            //确认链表数组位置      int hash  hash(key.hashCode());      int i  indexFor(hash, table.length);            //如果key相同则覆盖value部分      for (EntryK,V 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;      //添加链表节点      addEntry(hash, key, value, i);      return null;  }  下面看一下HashMap添加节点的实现 void addEntry(int hash, K key, V value, int bucketIndex) {   //bucketIndex 通过key的hash值与链表数组的长度计算得出      EntryK,V e  table[bucketIndex];      //创建链表节点          table[bucketIndex]  new EntryK,V(hash, key, value, e);        //判断是否需要扩容    if (size  threshold)              resize(2 * table.length);  }  以上部分的实现不会导致链路出现环链环链一般会出现HashMap扩容是下面看看扩容的实现: void resize(int newCapacity) {          Entry[] oldTable  table;          int oldCapacity  oldTable.length;          if (oldCapacity  MAXIMUM_CAPACITY) {              threshold  Integer.MAX_VALUE;              return;          }            Entry[] newTable  new Entry[newCapacity];                    transfer(newTable);//可能导致环链                    table  newTable;          threshold  (int)(newCapacity * loadFactor);  }  下面transfer的实现 void transfer(Entry[] newTable) {      Entry[] src  table;      int newCapacity  newTable.length;      for (int j  0; j  src.length; j) {          EntryK,V e  src[j];          if (e ! null) {              src[j]  null;              do {                  EntryK,V next  e.next;                  int i  indexFor(e.hash, newCapacity);                  e.next  newTable[i];                  newTable[i]  e;                  e  next;              } while (e ! null);          }      }  }  这个方法的目的是将原链表数据的数组拷到新的链表数组中拷贝过程中如果形成环链的呢下面用一个简单的例子来说明一下 public class InfiniteLoop {        static final MapInteger, Integer map  new HashMapInteger, Integer(2, 0.75f);        public static void main(String[] args) throws InterruptedException {            map.put(5, 55);            new Thread(Thread1) {              public void run() {                  map.put(7, 77);                  System.out.println(map);              };          }.start();            new Thread(Thread2) {              public void run() {                  map.put(3, 33);                  System.out.println(map);              };          }.start();        }    }  下面通过debug跟踪调试来看看如果导致HashMap形成环链断点位置 线程1的put操作线程2的put操作线程2的输出操作HashMap源码transfer方法中的第一行、第六行、第九行测试开始 使线程1进入transfer方法第一行此时map的结构如下2.  使线程2进入transfer方法第一行,此时map的结构如下 3.接着切换回线程1执行到transfer的第六行此时map的结构如下 4.然后切换回线程2使其执行到transfer方法的第六行此时map的结够如上 5.接着切换回线程1使其执行到transfer方法的第九行然后切换回线程2使其执行完此时map的结构如下 6.切换回线程1执行循环因为线程1之前是停在HashMap的transfer方法的第九行处所以此时transfer方法的节点e的key3e.next的key7 void transfer(Entry[] newTable) {          Entry[] src  table;          int newCapacity  newTable.length;          for (int j  0; j  src.length; j) {              EntryK,V e  src[j];              if (e ! null) {                  src[j]  null;                  do {                      EntryK,V next  e.next;                      int i  indexFor(e.hash, newCapacity);//线程1等线程2执行结束后                                                            //从此处开始执行                                                            //此时e的key3,e.next.key7                                                            //但是此时的e.next.next的key3了                                                            //被线程2修改了                      e.next  newTable[i];                      newTable[i]  e;                      e  next;                  } while (e ! null);              }          }  }  下面线程1开始执行第一次循环循环后的map结构如下 接着执行第二次循环e.key7,e.next.key3e.next.nextnull 接着执行第三次循环从而导致环链形成map结构如下 并且此时的map中还丢失了key5的节点
http://www.sadfv.cn/news/326830/

相关文章:

  • 网站制作的前期主要是做好什么工作沈阳手机网站开发
  • 手机图片网站模板软件开发技术方案模板
  • php网站用到的知识以背景做网站视频为
  • 网站建设推广小程序大连网站设计
  • 做网站构建高清设计网站推荐
  • 南宁门户网站有哪些网络工程建设
  • ui作品集 网站怎么做厦门律师网站建设
  • 衡阳网站建设怎样收费网站开发的前端到底是什么
  • 网站模板下载 网盘公司付网站会员费科目怎么做
  • 中文wordpress网站阿里云网站建设官方自营店
  • 如何个网站做优化企业网站推广优化公司
  • 网站改版阿里云怎么做网站301定向网络推广引流是什么意思
  • 网站防站杭州seo技术培训
  • 电商商城网站建设方案模拟建设网站
  • 网站添加提醒郑州中医男科哪个医院好
  • 给客户做网站图片侵权办图网ppt模板免费下载
  • 网页网站开发大概多少钱应用公园制作app软件下载
  • 网站有什么模块公司网站建设有用吗
  • 怎么做网站受众分析eechina电子工程网
  • 微博网站开发平台wordpress页面如何调用文章分类
  • 个人网站设计说明网站改版建设 有哪些内容
  • 如何建立网站建设电脑路由器做网站服务器
  • 道县找人做网站个人网站主页html5
  • 温州市建设安监局网站门户网站建设方案招标文件
  • 网络营销建设网站实训河北网站备案流程
  • 上海网站排名优化中国建筑最新消息
  • 个人网站备案麻烦页面好看的蛋糕网站
  • 哪家做网站的好wordpress 文章模块
  • 怎样做网站的快捷方式江苏建设信息网
  • 苏州手机网站制作wordpress添加自定义导航栏