您的位置:首页 > 其它

如何实现线程的HashMap以及性能对比

2016-12-24 11:52 387 查看
对于线程是否是安全的问题,一般是不会用到的,因为在开发中通用的是单线程倒是不用担心线程安全问题。

但是对于要进行高并发的开发,线程安全就必不可少了,这也是面试的拦路虎,在此总结一下前人的经验,进行线程安全的总结,如有不足的地方请指出交流。

借鉴别人的测试代码并完善一下:

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.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

public class CrunchifyConcurrentHashMapVsSynchronizedMap {

public final static int THREAD_POOL_SIZE = 10;
public final static int THREAD_LOOP_TIME = 100000;
public final static String key = "wordcounts" ;

public static Map<String, AtomicLong> crunchifyHashTableObject = null;

public static Map<String, AtomicLong> crunchifySynchronizedMapObject = null;

public static Map<String, AtomicLong> crunchifyConcurrentHashMapObject = null;
public static Map<String, AtomicLong> crunchifyHashMapObject = null;

public static void main(String[] args) throws

InterruptedException {
// 安全性测试
mapSecurictyTest();
//效率测试
mapEfficienceTest();
}

private static void mapSecurictyTest() throws InterruptedException {
// Test with HashMap Object
crunchifyHashMapObject = new HashMap<>();
threadSecurityTest(crunchifyHashMapObject);

// Test with Hashtable Object
crunchifyHashTableObject = new Hashtable<>();
threadSecurityTest(crunchifyHashTableObject);

// Test with synchronizedMap Object
crunchifySynchronizedMapObject = Collections.synchronizedMap(new HashMap<String, AtomicLong>());
threadSecurityTest(crunchifySynchronizedMapObject);

// Test with ConcurrentHashMap Object
crunchifyConcurrentHashMapObject = new ConcurrentHashMap<>();
threadSecurityTest(crunchifyConcurrentHashMapObject);

}

private static void mapEfficienceTest() throws InterruptedException {

// 效率最高 38ms
Map<String, Integer> crunchifyHashMapObject = null;

//	For class java.util.Hashtable the average time is 82 ms
Map<String, Integer> crunchifyHashTableObject = null;
//	For class java.util.Collections$SynchronizedMap the average time is 84 ms
Map<String, Integer> crunchifySynchronizedMapObject = null;
//	For class java.util.concurrent.ConcurrentHashMap the average time is 58 ms
Map<String, Integer> crunchifyConcurrentHashMapObject = null;

// Test with HashMap Object
crunchifyHashMapObject = new HashMap<>();
crunchifyPerformTest(crunchifyHashMapObject);

// Test with Hashtable Object
crunchifyHashTableObject = new Hashtable<>();
crunchifyPerformTest(crunchifyHashTableObject);

// Test with synchronizedMap Object
crunchifySynchronizedMapObject = Collections.synchronizedMap(new HashMap<String, Integer>());
crunchifyPerformTest(crunchifySynchronizedMapObject);

// Test with ConcurrentHashMap Object
crunchifyConcurrentHashMapObject = new ConcurrentHashMap<>();
crunchifyPerformTest(crunchifyConcurrentHashMapObject);
}

public static void threadSecurityTest( final Map<String, AtomicLong> map) throws InterruptedException {

System.out.println("Test started for: " + map.getClass());
long averageTime = 0;
for (int i = 0; i < 5; i++) {
long startTime = System.nanoTime();
ExecutorService crunchifyExServer = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
for (int j = 0; j < THREAD_POOL_SIZE; j++) {
crunchifyExServer.execute(new Runnable() {
@Override
public void run() {

for (int i = 0; i < THREAD_LOOP_TIME; i++) {
AtomicLong number = map.get(key);
if (number == null) {
AtomicLong newNumber = new AtomicLong(0);
number = map.putIfAbsent(key, newNumber);
if (number == null) {
number = newNumber;
}
}
long incrementValue = number.incrementAndGet();

if ((incrementValue )%500000==00) {
System.out.println("value is :" +(incrementValue ));
}

}
}
});
}

// Make sure executor stops
crunchifyExServer.shutdown();
// Blocks until all tasks have completed execution after a shutdown  request
crunchifyExServer.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);

long entTime = System.nanoTime();
long totalTime = (entTime - startTime) / 1000000L;
averageTime += totalTime;

System.out.println( (i+1 )+"-"+THREAD_POOL_SIZE*THREAD_LOOP_TIME +" entried added/retrieved in " + totalTime + " ms");
}
System.out.println("For " + map.getClass() + " the average time is " + averageTime / 5 + " ms\n");
}

public static void crunchifyPerformTest( final Map<String, Integer> crunchifyThreads) throws InterruptedException {

System.out.println("Test started for: " + crunchifyThreads.getClass());

long averageTime = 0;

for (int i = 0; i < 5; i++) {

long startTime = System.nanoTime();
ExecutorService crunchifyExServer = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
for (int j = 0; j < THREAD_POOL_SIZE; j++) {

crunchifyExServer.execute(new Runnable() {

@Override
public void run() {

for (int i = 0; i < THREAD_LOOP_TIME; i++) {

// Retrieve value. We are not using it anywhere
Integer crunchifyValue = crunchifyThreads.get(key);

// Put value
crunchifyThreads.put( key, new Integer(1));
}
}
});
}
// Make sure executor stops
crunchifyExServer.shutdown();
// Blocks until all tasks have completed execution after a shutdown  request
crunchifyExServer.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);

long entTime = System.nanoTime();
long totalTime = (entTime - startTime) / 1000000L;
averageTime += totalTime;

System.out.println("2500K entried added/retrieved in " + totalTime + " ms");
}
System.out.println("For " + crunchifyThreads.getClass() + " the average time is " + averageTime / 5 + " ms\n");
}

}


测试结果:
由打印结果发现 HashMap居然能够累加到500w.难道HashMap也能线程安全吗?

================================== map securicty test start ==================================

Test started for: class java.util.HashMap

value is :500000

value is :1000000

1-1000000 entried added/retrieved in 57 ms

value is :1500000

value is :2000000

2-1000000 entried added/retrieved in 51 ms

value is :2500000

value is :3000000

3-1000000 entried added/retrieved in 38 ms

value is :3500000

value is :4000000

4-1000000 entried added/retrieved in 35 ms

value is :4500000

value is :5000000

5-1000000 entried added/retrieved in 35 ms

For class java.util.HashMap the average time is 43 ms

Test started for: class java.util.Hashtable

value is :500000

value is :1000000

1-1000000 entried added/retrieved in 97 ms

value is :1500000

value is :2000000

2-1000000 entried added/retrieved in 66 ms

value is :2500000

value is :3000000

3-1000000 entried added/retrieved in 67 ms

value is :3500000

value is :4000000

4-1000000 entried added/retrieved in 65 ms

value is :4500000

value is :5000000

5-1000000 entried added/retrieved in 61 ms

For class java.util.Hashtable the average time is 71 ms

Test started for: class java.util.Collections$SynchronizedMap

value is :500000

value is :1000000

1-1000000 entried added/retrieved in 111 ms

value is :1500000

value is :2000000

2-1000000 entried added/retrieved in 90 ms

value is :2500000

value is :3000000

3-1000000 entried added/retrieved in 92 ms

value is :3500000

value is :4000000

4-1000000 entried added/retrieved in 94 ms

value is :4500000

value is :5000000

5-1000000 entried added/retrieved in 98 ms

For class java.util.Collections$SynchronizedMap the average time is 97 ms

Test started for: class java.util.concurrent.ConcurrentHashMap

value is :500000

value is :1000000

1-1000000 entried added/retrieved in 40 ms

value is :1500000

value is :2000000

2-1000000 entried added/retrieved in 35 ms

value is :2500000

value is :3000000

3-1000000 entried added/retrieved in 32 ms

value is :3500000

value is :4000000

4-1000000 entried added/retrieved in 34 ms

value is :4500000

value is :5000000

5-1000000 entried added/retrieved in 33 ms

For class java.util.concurrent.ConcurrentHashMap the average time is 34 ms

================================== map securicty test end ==================================

带着疑问再次进行单独测试:

Test started for: class java.util.HashMap

value is :500000

1-1000000 entried added/retrieved in 51 ms

value is :1000000

value is :1500000

2-1000000 entried added/retrieved in 40 ms

value is :2000000

value is :2500000

3-1000000 entried added/retrieved in 31 ms

value is :3000000

value is :3500000

4-1000000 entried added/retrieved in 30 ms

value is :4000000

value is :4500000

5-1000000 entried added/retrieved in 30 ms

For class java.util.HashMap the average time is 36 ms

发现这次就没有能够达到线程安全。

所以线程安全的策略有三种,而且要和atomic结合操作才能实现。

效率测试如下:

HashMap的效率最高,如果不考虑线程的问题(单线程使用的时候),HashMap是首选。

其次是ConcurrentHashMap,Collections$SynchronizedMap,Hashtable 。

一般情况下ConcurrentHashMap效率能够达到Collections$SynchronizedMap或者Hashtable 的两倍,

================================== map Efficience test start ==================================

Test started for: class java.util.HashMap

2500K entried added/retrieved in 58 ms

2500K entried added/retrieved in 49 ms

2500K entried added/retrieved in 26 ms

2500K entried added/retrieved in 27 ms

2500K entried added/retrieved in 28 ms

For class java.util.HashMap the average time is 37 ms

Test started for: class java.util.Hashtable

2500K entried added/retrieved in 113 ms

2500K entried added/retrieved in 76 ms

2500K entried added/retrieved in 72 ms

2500K entried added/retrieved in 75 ms

2500K entried added/retrieved in 74 ms

For class java.util.Hashtable the average time is 82 ms

Test started for: class java.util.Collections$SynchronizedMap

2500K entried added/retrieved in 100 ms

2500K entried added/retrieved in 87 ms

2500K entried added/retrieved in 88 ms

2500K entried added/retrieved in 84 ms

2500K entried added/retrieved in 87 ms

For class java.util.Collections$SynchronizedMap the average time is 89 ms

Test started for: class java.util.concurrent.ConcurrentHashMap

2500K entried added/retrieved in 63 ms

2500K entried added/retrieved in 58 ms

2500K entried added/retrieved in 58 ms

2500K entried added/retrieved in 57 ms

2500K entried added/retrieved in 60 ms

For class java.util.concurrent.ConcurrentHashMap the average time is 59 ms

================================== map Efficience test end ==================================

参考: http://blog.csdn.net/cnhk1225/article/details/52413201
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐