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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LoveTea99/article/details/53044806
看到大型网站系统与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。

展开阅读全文

没有更多推荐了,返回首页