参考资料:
https://crunchify.com/hashmap-vs-concurrenthashmap-vs-synchronizedmap-how-a-hashmap-can-be-synchronized-in-java/
https://stackoverflow.com/questions/35534906/java-hashmap-getobject-infinite-loop
Map的一些实现类有及其特性
类
线程安全
特性
Hashtable
是
Key不能为null
HashMap
否
读写效率最高,但在Java6多线程环境下使用不当可能陷入死循环,进而导致CPU使用率过高(原理可参见:http://coolshell.cn/articles/9606.html)
Collections.synchronizedMap
是
Collections.SynchronizedMap在Map所有方法基础上加锁,效率与HashTable相当
ConcurrentHashMap
是
采用分段锁,get一般不加锁,put分段锁,key/value不能为null,效率仅次于HashMap
以下代码测试各类的读写效率
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* @Description: 测试map
*/
public class ThreadMapTest {
public static void main(String[] args) throws InterruptedException {
Map hashtable = new Hashtable<>();
Map hashmap = new HashMap<>();
Map synchronizedHashMap = Collections.synchronizedMap(new HashMap<>());
Map concurrentHashMap = new ConcurrentHashMap<>();
test(hashtable);
test(hashmap);
test(synchronizedHashMap);
test(concurrentHashMap);
}
private static void test(Map map) throws InterruptedException {
int testTimes = 5;
long totalTimeMillis = 0;
for (int k = 0; k < testTimes; k++) {
totalTimeMillis += costTimeMillis(map);
}
System.out.println("Test " + map.getClass() + " average time " + (totalTimeMillis / testTimes));
}
private static long costTimeMillis(Map map) throws InterruptedException {
int count = 5;
ExecutorService executorService = Executors.newFixedThreadPool(count);
long startMillis = System.currentTimeMillis();
for (int i = 0; i < count; i++) {
executorService.execute(new Runnable() {
@Override
public void run() {
for (int j = 0; j < 500000; j++) {
map.put(0, 0);
map.get(0);
}
}
});
}
executorService.shutdown();
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
return System.currentTimeMillis() - startMillis;
}
}
输出结果如下:
Test class java.util.Hashtable average time 267
Test class java.util.HashMap average time 67
Test class java.util.Collections$SynchronizedMap average time 262
Test class java.util.concurrent.ConcurrentHashMap average time 167