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 |
以下代碼測試各類的讀寫效率:
package com.concurrent.test; 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; /** * 測試map */ public class ThreadMapTest { public static void main(String[] args) throws InterruptedException { Map<Integer, Integer> hashtable = new Hashtable<>(); Map<Integer, Integer> hashmap = new HashMap<>(); Map<Integer, Integer> synchronizedHashMap = Collections.synchronizedMap(new HashMap<Integer, Integer>()); Map<Integer, Integer> concurrentHashMap = new ConcurrentHashMap<>(); test(hashtable); test(hashmap); test(synchronizedHashMap); test(concurrentHashMap); } private static void test(Map<Integer, Integer> 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(final Map<Integer, Integer> 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 < 50000; 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 104 Test class java.util.HashMap average time 31 Test class java.util.Collections$SynchronizedMap average time 79 Test class java.util.concurrent.ConcurrentHashMap average time 66