前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于hashmap在多线程环境下的一个小实验

关于hashmap在多线程环境下的一个小实验

作者头像
java达人
发布2018-01-31 18:16:15
1.1K0
发布2018-01-31 18:16:15
举报
文章被收录于专栏:java达人

我们都知道hashmap是非线程安全的,平时我们经常是在单线程环境下使用这个类的,现在我们模拟一个多线程环境,并发操作访问一个hashmap实例,看看会出现什么匪夷所思的问题。

运行如下程序:

代码语言:js
复制
import java.util.HashMap;
public class TestMap {
 private HashMap map = new HashMap(2, 0.5f);
 public TestMap() {
  Thread t1 = new Thread() {
   public void run() {
    for (int i = 0; i < 50000; i++) {
     map.put(new Integer(i), i);
    }
    System.out.println("t1 over");
   }
  };
  Thread t2 = new Thread() {
   public void run() {
    for (int i = 0; i < 50000; i++) {
     map.put(new Integer(i), i);
    }
    System.out.println("t2 over");
   }
  };
  Thread t3 = new Thread() {
   public void run() {
    for (int i = 50000; i < 100000; i++) {
     map.put(new Integer(i), i);
    }
    System.out.println("t3 over");
   }
  };
  Thread t4 = new Thread() {
   public void run() {
    for (int i = 100000; i < 150000; i++) {
     map.put(new Integer(i), i);
    }
    System.out.println("t4 over");
   }
  };
  Thread t5 = new Thread() {
   public void run() {
    for (int i = 150000; i < 200000; i++) {
     map.put(new Integer(i), i);
    }
    System.out.println("t5 over");
   }
  };
  Thread t6 = new Thread() {
   public void run() {
    for (int i = 0; i < 50000; i++) {
     map.get(new Integer(i));
    }
    System.out.println("t6 over");
   }
  };
  Thread t7 = new Thread() {
   public void run() {
    for (int i = 50000; i < 100000; i++) {
     map.get(new Integer(i));
    }
    System.out.println("t7 over");
   }
  };
  Thread t8 = new Thread() {
   public void run() {
    for (int i = 100000; i < 150000; i++) {
     map.get(new Integer(i));
    }
    System.out.println("t8 over");
   }
  };
  t1.start();
  t2.start();
  t3.start();
  t4.start();
  t5.start();
  t6.start();
  t7.start();
  t8.start();
 }
 public static void main(String[] args) {
  new TestMap();
 }
}

刚开始我并未给构造器指定参数,为了提高问题复现的机率,我把map的初始容量和负载因子分别设为2和0.5,这样map的rehash操作就更加频繁了,多点击运行一下,就会发现有几个线程没有打印出结束标志,这是什么原因,难道线程可能进入了等待状态,或者死循环?

查看任务管理器,发现javaw线程cpu竟超过80%

利用jstack工具查看堆栈信息:

线程处于运行状态,程序进入了死循环,多个线程同时put,rehash的时候会导致循环链表的出现,用get方法获取就会出现inifinite loop。(疫苗:Java HashMap的死循环)这个问题现在看来一目了然,但在生产环境上,系统庞大,要找出问题根源是需要费一段时间的,当hashmap出现了让人匪夷所思的现象时,要想想它是否处于多线程环境。

另外,在运行这段代码时,有时也会报出如下异常:

Exception in thread "Thread-2" java.lang.ArrayIndexOutOfBoundsException: 26

at java.util.HashMap.getEntry(HashMap.java:463)

at java.util.HashMap.get(HashMap.java:417)

at map.TestMap$3.run(TestMap.java:36)

直接看源码可知,问题还是出在多个线程同时操作访问table变量上。

或许你在多线程环境下使用hashmap过程中碰到更多有趣的现象,请留言或投稿给我。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-04-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java达人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档