直接用ConcurrentHashMap代替HashMap引发的问题

来源:互联网 发布:淘宝身份认证失败 编辑:程序博客网 时间:2024/06/05 01:16
看到大型网站系统与Java中间件实践里边有提到直接将HashMap替换成ConcurrentHashMap时会有问题,所以我写了一段代码测试一下,测试一个数组中字符串出现的次数,结果真的有问题额。
package com.yy.ent.platform.ecommerce.common;import java.util.Map.Entry;  import java.util.concurrent.ConcurrentHashMap; public class ConHashMapTest { private static ConcurrentHashMap<String,Integer> map = new ConcurrentHashMap<String,Integer>();   private static String[] array = {"yy","yy","welcome","java","234","java","1234","yy","welcome","java","234"};            public static void main(String[] args) {            System.out.println("array size:"+array.length);          for (String str : array) {              new Thread(new MyTask(str)).start();          }            for(Entry<String,Integer> entry : map.entrySet()){              System.out.println(entry.getKey()+":"+entry.getValue());          }      }        static class MyTask implements Runnable{          String key;            public MyTask(String key) {              this.key = key;          }          @Override          public void run() {        map.putIfAbsent(key, value)            Integer value = map.get(key);              if(null == value){                  map.put(key, 1);              }else{                  map.put(key, value + 1);              }            }        }      }  

运行结果:


很明显结果不正确。因为我们对map的值修改要依赖上一次的值,在多线程的环境下就会出问题,如果对于key相同就会发生漏统计,但是我还是比较疑惑测试出来的结果,key为什么会少呢,下面我对map加锁然后程序产生正确结果。

package com.yy.ent.platform.ecommerce.common;import java.util.Map.Entry;  import java.util.concurrent.ConcurrentHashMap; public class OptimizedConHashMapTest {private static ConcurrentHashMap<String,Integer> map = new ConcurrentHashMap<String,Integer>();  private static String[] array = {"yy","yy","welcome","java","234","java","1234","yy","welcome","java","234"};  public static void main(String[] args) {  System.out.println("array size:"+array.length);  for (String str : array) {  new Thread(new MyTask(str)).start();  }  for(Entry<String,Integer> entry : map.entrySet()){  System.out.println(entry.getKey()+":"+entry.getValue());  }  }  static class MyTask implements Runnable{  String key;  public MyTask(String key) {  this.key = key;  }  @Override  public void run() {  synchronized(map){Integer value = map.get(key);  if(null == value){  map.put(key, 1);  }else{  map.put(key, value + 1);  }  }}  }  }

运行结果:

结果正确。如果对于值的修改要依赖上一次的值,还是直接给HashMap加锁实现好了;如果修改的值不依赖上一次的值就用ConcurrentHashMap。

1 0
原创粉丝点击