我想比较ConcurrentHashMap
和ConcurrentSkipListMap
之间的效果。它用于研究目的。结果是结果取决于平台到平台。在我的计算机上,预期阅读测试ConcurrentHashMap
比ConcurrentSkipListMap
更有效率。但写作测试表现出更多的表现ConcurrentSkipListMap
。 ConcurrentHashMap
依赖于哈希表,我认为它应该更快。为什么会这样?
package Concurrency;
import java.util.*;
import java.util.concurrent.*;
abstract class Task implements Callable<Long> {
protected static Map<Integer, String> map;
protected int nIteration;
protected static int index;
protected long startTime, endTime;
private static Random random = new Random();
private static char[] chars = "abcdefghijklmnopqrstuvwxyz".toCharArray();
public Task(Map<Integer, String> map, int nIteration) {
Task.map = map;
this.nIteration = nIteration;
}
protected static synchronized String getNextString() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 5; i++) {
char c = chars[random.nextInt(chars.length)];
sb.append(c);
}
sb.append(index);
return sb.toString();
}
protected static synchronized int getNextInt() { return index++; }
protected static synchronized int getPreviousInt() { return index--; }
protected static synchronized int getCurrentInt() { return index; } // It's for test purpose.
public abstract Long call();
}
class WriterTask extends Task {
public WriterTask(Map<Integer, String> map, int nIteration) { super(map, nIteration); }
public Long call() {
startTime = System.currentTimeMillis();
while(nIteration-- > 0) {
map.put(getNextInt(), getNextString());
}
endTime = System.currentTimeMillis();
return (endTime - startTime);
}
}
class ReaderTask extends Task {
public ReaderTask(Map<Integer,String> map, int nIteration) { super(map, nIteration); }
@Override
public Long call() {
startTime = System.currentTimeMillis();
while(nIteration-- > 0) {
map.remove(getPreviousInt());
}
endTime = System.currentTimeMillis();
return (endTime - startTime);
}
}
public class FourtyThree {
private static List<Future<Long>> result = new LinkedList<>();
private static Map<Integer, String> map;
//private static String mapName;
private static Map<String, Double> makeReport(
int nCycle, int nThreads, boolean isWriter , int nIteration)
throws InterruptedException, ExecutionException {
Long resultTime = 0L;
int numberLine = 0;
double resultAverage;
StringBuilder sb = new StringBuilder();
sb.append(map.getClass().getSimpleName());
sb.append(", Cycle:" + nCycle);
if(isWriter)
sb.append(", Test type:Writing");
else
sb.append(", Test type: Reading");
sb.append(", iteration:" + nIteration);
sb.append(", Threads:" +nThreads);
for(Future<Long> i : result) {
resultTime += i.get();
numberLine++;
}
resultAverage = (double)resultTime / (double)numberLine;
resultAverage = (double)Math.round(resultAverage * 100) / 100;
sb.append(", Average time:" + resultAverage + " milliseconds");
return Collections.singletonMap(sb.toString(), resultAverage);
}
private static void prepareReading(int nIteration) {
ExecutorService exec = Executors.newSingleThreadExecutor();
exec.submit(new WriterTask(map, nIteration));
exec.shutdown();
}
public static Map<String, Double> test( Map<Integer, String> testMap,
int nCycle,
int nThreads,
boolean isWriter ,
int nIteration )
throws InterruptedException, ExecutionException {
map = testMap;
if (!isWriter)
prepareReading(nThreads * nIteration);
ExecutorService exec = Executors.newFixedThreadPool(nThreads);
List<Callable<Long>> tasks = new LinkedList<>();
for(int i = 0; i < nThreads; i++) {
if(isWriter)
tasks.add(new WriterTask(map, nIteration));
else
tasks.add(new ReaderTask(map, nIteration));
}
result = exec.invokeAll(tasks);
exec.shutdown();
map.clear();
return makeReport(nCycle, nThreads, isWriter , nIteration);
}
public static void main(String[] args) throws InterruptedException, ExecutionException {
Map<String, Double> results = new LinkedHashMap<String, Double>();
Collection<Double> resultTime = results.values();
double time = 0;
ConcurrentHashMap<Integer, String> map1 = new ConcurrentHashMap<>();
ConcurrentSkipListMap<Integer, String> map2 = new ConcurrentSkipListMap<>();
for(int i = 0; i < 5; i++) {
results.putAll(test(map1, i, 16, false, 1000));
}
for(Map.Entry<String, Double> entry : results.entrySet()) {
System.out.println(entry.getKey());
time += entry.getValue();
}
time = time / (double)resultTime.size();
time = Math.round(time * 100) / 100;
System.out.print("Average time for all cycles:" + time);
System.out.print(", Max time:" + Collections.max(resultTime));
System.out.print(", Min time:" + Collections.min(resultTime));
}
}
/* Short report:
*** Reading ***
ConcurrentHashMap, Cycle:4, Test type: Reading, iteration:1 000 000, Threads:2
Average time for all cycles:3530.0, Max time:6817.5, Min time:1625.0
ConcurrentSkipListMap, Cycle:4, Test type: Reading, iteration:1 000 000, Threads:2
Average time for all cycles:4716.0, Max time:9337.5, Min time:1294.0
ConcurrentHashMap, Cycle:4, Test type: Reading, iteration:100 000, Threads:16
Average time for all cycles:528.0, Max time:1064.06, Min time:355.25
ConcurrentSkipListMap, Cycle:4, Test type: Reading, iteration:100 000, Threads:16
Average time for all cycles:1081.0, Max time:1732.75, Min time:330.5
*** Writing ***
ConcurrentHashMap, Cycle:4, Test type:Writing, iteration:1 000 000, Threads:2
Average time for all cycles:12112.1, Max time:18261.5, Min time:9111.5
ConcurrentSkipListMap, Cycle:4, Test type:Writing, iteration:1 000 000, Threads:2
Average time for all cycles:11856.7, Max time:18143.0, Min time:8292.0
ConcurrentHashMap, Cycle:4, Test type:Writing, iteration:100 000, Threads:16
Average time for all cycles:9015.0, Max time:16461.75, Min time:5016.5
ConcurrentSkipListMap, Cycle:4, Test type:Writing, iteration:100 000, Threads:16
Average time for all cycles:8922.68, Max time:12383.31, Min time:6783.13
*/