创建一个线程安全的Map,数据测试

如何创建一个线程安全的Map?
1,使用普通的旧的Hashtable

HashMap允许null作为key,而Hashtable不可以

2,使用Collections中同步化的包装方法synchronizedMap

3,使用concurrent包下的ConcurrentHashMap

	//Hashtable Example Code
	Map<String, Integer> threadSafeMap = new Hashtable<String, Integer>();
	//synchronizedMap Example Code.
	threadSafeMap = Collections.synchronizedMap(new HashMap<String, Integer>());
	//ConcurrentHashMap Example Code
	threadSafeMap = new ConcurrentHashMap<String, Integer>();
	threadSafeMap .put("Key1", 123);

ConcurrentHashMap 性能最好

HashMap线程不安全的体现

  1. resize死循环
  2. fail-fast
    如果在使用迭代器的过程中有其他线程修改了map,那么将抛出ConcurrentModificationException,这就是所谓fail-fast策略。

这个异常意在提醒开发者及早意识到线程安全问题,具体原因请查看ConcurrentModificationException的原因以及解决措施

测试三种并发集合的读写效率

import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

//测试三种并发集合的读写效率
public class ConcurrentHashMapTest {

    public static void main(String[] args) {
        //HashMap不是线程安全的,通过 Collections.synchronizedMap()转换成线程安全的.
        final Map<Integer, Integer> hm = Collections.synchronizedMap(new HashMap<Integer, Integer>());
        //HashTable内部自带同步,线程安全的.
        final Map<Integer, Integer> ht = new Hashtable<Integer, Integer>();
        //JDK1.5之后提供的并发集合.
        final Map<Integer, Integer> chm = new ConcurrentHashMap<Integer, Integer>();
        putMap(hm);//
        putMap(ht);//
        putMap(chm);//数据量达到一定程度之后,会比前两种快3~4倍左右.
        //TODO JDK1.8
//      8312
//      7053
//      6712
        //TODO JDK1.7
//      8672
//      8332
//      6842
        
    }

    private static void putMap(final Map<Integer, Integer> hm) {
        long begin = System.currentTimeMillis();
        for (int k = 0; k < 100; k++) {//为了让效果更明显,再循环100次.
            for (int i = 0; i < 1000; i++) {//1000条线程
                final int key = i;
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        for (int j = 0; j < 1000; j++) {//每条线程向其中添加1000次
                            hm.put(key, j);
                        }
                    }
                }).start();
            }
        }
        long end = System.currentTimeMillis();
        System.out.println(end - begin);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_25958497/article/details/82824468