Single Thread
HashMap and TreeMap can be used in single-threaded environments. The TreeMap on the traversal return results are sorted by key.
Test method
Record the time, in milliseconds, of the N records written to the map.
Records the time, in milliseconds, of reading 10W records from a map of N records.
n=25w,50w,75w,100w
Test results
Write N Records |
25W |
50W |
75W |
100W |
HashMap |
28 |
49 |
72 |
92 |
TreeMap |
131 |
321 |
527 |
748 |
Read 10W data in N Records |
25W |
50W |
75W |
100W |
HashMap |
4 |
5 |
5 |
5 |
TreeMap |
38 |
42 |
47 |
47 |
Results Analysis
TreeMap is implemented with red-black trees, the lookup is a binary lookup, the time complexity is O (log (n)), the worst-case time complexity is O (n), and the time complexity of the HashMap lookup is O (1).
The test results also show that TreeMap's reading and writing performance is much worse than HashMap.
therefore, in a single-threaded environment, if it is not necessary to sort by key in order to return the results, you should use HashMap.
Multithreading
The following four map containers can be used in a multithreaded environment.
1) Collections.synchronizedmap (new HashMap ());
2) Concurrenthashmap
3) Collections.synchronizedsortedmap (new TreeMap ())
4) Concurrentskiplistmap
Test method
Start the n write thread first, and each write thread writes to the 100w/n record in the map.
After the n-read thread is started, each read thread reads the 10W record from the map in the 100W record.
Records the write/read time per thread, in milliseconds.
Perform the test on a 8-core Intel CPU.
Test results
|
1 Synchronizedhashmap |
2 Concurrenthashmap |
3 Synchronizedtreemap |
4 Concurrentskiplistmap |
Number of Threads N=1 |
Write time:104 Read Time:9 |
Write time:135 Read time:10 |
Write time:760 Read time:50 |
Write time:1349 Read time:156 |
Number of Threads n=2 |
Write time:168 Write time:169 Read time:20 Read time:24 |
Write time:84 Write time:97 Read time:11 Read time:11 |
Write time:819 Write time:873 Read time:125 Read time:124 |
Write time:676 Write time:682 Read time:152 Read time:153 |
Number of Threads n=4 |
Write time:175 Write time:187 Write time:188 Write time:189 Read time:49 Read time:52 Read time:53 Read time:60 |
Write time:50 Write time:52 Write time:54 Write time:55 Read time:11 Read Time:12 Read time:15 Read time:15 |
Write time:890 Write time:917 Write time:928 Write time:944 Read time:271 Read time:277 Read time:280 Read time:283 |
Write time:365 Write time:368 Write time:385 Write time:386 Read time:174 Read time:178 Read time:177 Read time:179 |
Number of Threads n=8 |
Write time:174 Write time:174 Write time:175 Write time:178 Write time:178 Write time:179 Write time:178 Write time:178 Read time:112 Read time:114 Read time:116 Read time:117 Read time:118 Read time:175 Read time:176 Read time:176 |
Write time:55 Write time:32 Write time:56 Write time:56 Write time:57 Write time:56 Write time:56 Write time:58 Read time:13 Read time:13 Read time:13 Read time:14 Read time:14 Read time:15 Read time:16 Read time:14 |
Write time:807 Write time:821 Write time:869 Write time:904 Write time:914 Write time:933 Write time:938 Write time:941 Read time:565 Read time:584 Read time:594 Read time:614 Read time:615 Read time:619 Read time:679 Read time:686 |
Write time:193 Write time:194 Write time:201 Write time:209 Write time:217 Write time:222 Write time:250 Write time:285 Read time:177 Read time:177 Read time:179 Read time:180 Read time:180 Read time:186 Read time:240 Read time:256 |
Results Analysis
Collections.synchronizedmap and Collections.synchronizedsortedmap are actually wrapping the incoming map object, with each method with a lock.
The implementation of CONCURRENTHASHMAP uses a segmented lock and other techniques, the multi-threaded environment read without lock, write also get a great degree of optimization.
The implementation of CONCURRENTSKIPLISTMAP uses the data structure of the jumping table, which is born for concurrent operation and can be read without lock in the same multithreaded environment.
Concurrentskiplistmap and TreeMap are the same, the lookup is a binary lookup, and the traversal needs to be sorted by key to return the result.
Single-threaded environment, there is no doubt that synchronizedhashmap better than concurrenthashmap;synchronizedtreemap better than Concurrentskiplistmap.
As the number of threads increases, Concurrenthashmap reads and writes better than Synchronizedhashmap.
Since the read does not need to lock, Concurrenthashmap and Concurrentskiplistmap read time are basically not increased with the number of threads,
and Synchronizedhashmap and Synchronizedtreemap, because read also to lock, then as the number of threads increased read time also increased.
In particular, under 8 threads, Concurrentskiplistmap's read and write efficiency is almost synchronizedhashmap. If the number of threads increases again, the Concurrentskiplistmap performance should exceed Synchronizedhashmap.
So in a multithreaded environment,
If you do not need to traverse the need to follow the order of key to return the results, preferred concurrenthashmap;
If you need to traverse the order of key to return the results, preferred concurrentskiplistmap.
===========================================================================================
Test program
Package Learning.multithread.collection;import Java.util.arraylist;import Java.util.collections;import Java.util.hashmap;import Java.util.list;import Java.util.map;import Java.util.treemap;import Java.util.concurrent.concurrenthashmap;import java.util.concurrent.concurrentskiplistmap;/** * set-xms1024m to Avoid JVM heap size increase during the test */public class Concurrentmaptest {private static final int thread_num = 8; private static final int map_size = 1000000; public static void Main (string[] args) throws Interruptedexception {list<integer> List = new Arraylist<in Teger> (map_size); for (int i = 0; i < map_size; i++) {List.add (integer.valueof (i)); } collections.shuffle (list); Singlethreadmaptest (New Hashmap<integer, integer> (), list); Singlethreadmaptest (New Treemap<integer, integer> (), list); Concurrentmaptest (Collections.synchronizedmap (newHashmap<integer, Integer> ()), list); Concurrentmaptest (New Concurrenthashmap<integer, integer> (), list); Concurrentmaptest (Collections.synchronizedsortedmap (New Treemap<integer, integer> ()), list); Concurrentmaptest (New Concurrentskiplistmap<integer, integer> (), list); } private static void Singlethreadmaptest (Map<integer, integer> Map, list<integer> l) {//first Run to load memories and set map Initial size mapreadwrite (map, L); Mapreadwrite (map, L); Map.clear (); System.out.println ("Now start Test ..."); Mapreadwrite (map, l.sublist (0, (MAP_SIZE/4))); Map.clear (); Mapreadwrite (map, l.sublist (0, (MAP_SIZE/4))); Map.clear (); Mapreadwrite (map, l.sublist (0, (MAP_SIZE/4))); Map.clear (); Mapreadwrite (map, L); } private static void Mapreadwrite (Map<integer, integer> Map, list<integer> L){Mapwriter Mwhash = new Mapwriter (map, L); Mwhash.run (); Mapreader Mrhash = new Mapreader (map, l.sublist (0, (MAP_SIZE/10))); Mrhash.run (); System.out.println ("Map Size =" + map.size ()); } private static void Concurrentmaptest (Map<integer, integer> Map, list<integer> L) throws Interruptede Xception {//first Run to load all to memories and set map Initial size concurrentreadwrite (map, L); Map.clear (); Concurrentreadwrite (map, L); Map.clear (); System.out.println ("Now start Test ..."); Concurrentreadwrite (map, L); System.out.println ("Map Size =" + map.size ()); } private static void Concurrentreadwrite (Map<integer, integer> Map, list<integer> L) throws interruptedexception {thread[] writerthreads = new Thread[thread_num]; thread[] readerthreads = new Thread[thread_num]; int mapSize = Map_size/thread_num; for (int i = 0; i < Thread_num; ++i) {writerthreads[i] = new THREAD (new Mapwriter (map, L.sublist (Mapsize*i, mapsize* (i+1))); } for (int i = 0; i < Thread_num; ++i) {Writerthreads[i].start (); } for (Thread t:writerthreads) {t.join (); } for (int i = 0; i < Thread_num; ++i) {readerthreads[i] = new THREAD (new Mapreader (map, L.s Ublist (Mapsize*i, MAPSIZE*I+MAP_SIZE/10)); } for (int i = 0; i < Thread_num; ++i) {Readerthreads[i].start (); } for (Thread t:readerthreads) {t.join (); }} private static class Mapwriter implements Runnable {public mapwriter (Map<integer, integer> ma P, list<integer> l) {this.map = map; THIS.L = l; public void Run () {Long begin = System.currenttimemillis (); for (Integer i:l) {map.put (I, I); } Long end = System.currenttimemillis (); System.out.println ("Write Time:" + (End-begin)); } private Final Map<integer, integer> Map; Private Final list<integer> L; } private static Class Mapreader implements Runnable {public Mapreader (Map<integer, integer> Map, Lis T<integer> l) {this.map = map; THIS.L = l; public void Run () {Long begin = System.currenttimemillis (); for (Integer i:l) {map.get (i); } Long end = System.currenttimemillis (); System.out.println ("Read Time:" + (End-begin)); } private Final Map<integer, integer> Map; Private Final list<integer> L; }}
Java Multithreading--map container performance comparison