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

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

 

运行如下程序:

 

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过程中碰到更多有趣的现象,请留言或投稿给我。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值