【译】Java Hashtable、HashMap和ConcurrentHashMap之间的性能差异转载
有很多文章阐明了 HashMap、HashTable 和 ConcurrentHashMap 之间的功能差异。
这篇文章通过实际示例比较了这些数据结构的性能。
如果您没有耐心阅读整篇文章,那么结论是:当你面临使用 HashMap 或 HashTable 或 ConcurrentHashMap 的决定时,您可以考虑使用 ConcurrentHashMap,因为它是线程安全的实现,不会影响性能.
性能研究
为了研究性能特征,我整理了这个示例程序:
1 public class HashMapPerformance {
2
3 public static int ITERATION_COUNT = 10000000;
4
5 private static AtomicInteger exitThreadCount = new AtomicInteger(0);
6
7 public static HashMap<Integer, Integer> myHashMap;
8
9 public static void initData() {
10
11 myHashMap = new HashMap<>(1000);
12
13 for (int counter = 0; counter < 1000; ++counter) {
14
15 myHashMap.put(counter, counter);
16 }
17 }
18
19 private static class Writer extends Thread{
20
21 public void run() {
22
23 Random random = new Random();
24
25 for (int iteration = 0; iteration < ITERATION_COUNT; ++iteration) {
26
27 int counter = random.nextInt(1000 - 1);
28 myHashMap.put(counter, counter);
29 }
30
31 exitThreadCount.incrementAndGet();
32 }
33 }
34
35 private static class Reader extends Thread{
36
37 public void run() {
38
39 Random random = new Random();
40
41 for (int iteration = 0; iteration < ITERATION_COUNT; ++iteration) {
42
43 int counter = random.nextInt(1000 - 1);
44 myHashMap.get(counter);
45 }
46
47 exitThreadCount.incrementAndGet();
48 }
49 }
50
51 public static void main (String args[]) throws Exception {
52
53 initData();
54
55 long start = System.currentTimeMillis();
56
57 // Create 10 Writer Threads
58 for (int counter = 0; counter < 10; ++counter) {
59
60 new Writer().start();
61 }
62
63 // Create 10 Reader Threads
64 for (int counter = 0; counter < 10; ++counter) {
65
66 new Reader().start();
67 }
68
69 // Wait for all threads to complete
70 while (exitThreadCount.get() < 20) {
71 Thread.sleep(100);
72 }
73
74 System.out.println("Total execution Time(ms): " + (System.currentTimeMillis() - start) );
75 }
76 }
该程序触发多个线程对“java.util.HashMap”进行并发读写。
让我们来看看这段代码。该程序中的主要对象是第 7 行中定义的“myHashMap”。该对象的类型为“java.util.HashMap”,并在第 9 行中定义的方法“initData()”中使用 1000 条记录进行了初始化。HashMap 中的 key 和 value 都具有相同的整数值。因此,这个 HashMap 将如下图所示:
钥匙 | 价值 |
0 | 0 |
1 | 1 |
2 | 2 |
3 | 3 |
: | : |
: | : |
1000 | 1000 |
图:HashMap 中的数据
'Writer' 线程在第 19 行中定义。该线程生成一个 0 到 1000 之间的随机数,并将生成的数字插入到 HashMap 中,重复 1000 万次。我们随机生成数字,以便记录可以插入到 HashMap 数据结构的不同部分。同样,第 35 行定义了一个“Reader”线程。该线程生成一个 0 到 1000 之间的随机数,并从 HashMap 中读取生成的数字。
你还可以注意到第 51 行中定义的 'main()' 方法。在这个方法中,将你看到创建并启动了 10 个“编写器”线程。同样,创建并启动了 10 个“阅读器”线程。然后在第 70 行,有一个代码逻辑将阻止程序终止,直到所有 Reader 和 Writer 线程完成它们的工作。
HashMap 性能
我们多次执行上述程序。程序平均执行时间为3.16 秒
Hashtable性能
为了研究 Hashtable 的性能,我们将第 7 行替换为 'java.util.Hashtable' 并修改了 'Reader' 和 'Writer' 线程以从 'HashTable' 中读取和写入。然后我们多次执行该程序。该程序的平均执行时间为56.27 秒。
ConcurrentHashMap 性能
为了研究 HashTable 的性能,我们基本上用 'java.util.concurrent.ConcurrentHashMap' 替换了第 7 行,并修改了 'Reader' 和 'Writer' 线程以从 'ConcurrentHashMap' 读取和写入。然后我们多次执行该程序。该程序的平均执行时间为4.26 秒。
HashMap、Hashtable、ConcurrentHashMap 性能对比
下表总结了每个数据结构的执行时间:
数据结构 | 执行时间(秒) |
HashMap | 3.16 |
ConcurrentHashMap | 4.26 |
Hashtable | 56.27 |
如果你注意到 HashMap 具有最佳性能,但它不是线程安全的。它有一个可怕的问题,可能导致线程进入无限循环,最终导致 应用程序的 CPU 飙升。
如果你注意到 ConcurrentHashMap 的执行速度比 HashMap 稍慢,但它是 100% 线程安全的实现。
另一方面 Hashtable 也是线程安全的实现,但在这个测试场景中 它比 HashMap 慢 18 倍。
为什么 Hashtable 这么慢?
Hashtable 之所以这么慢,是因为这个对象上的 'get()' 和 'put()' 方法都是同步的(如果你有兴趣,可以在这里查看 Hashtable 源代码)。当一个方法被同步时,在任何给定的时间点,只有一个线程被允许调用它。
在我们的示例程序中有 20 个线程。10 个线程正在调用“get()”方法,另外 10 个线程正在调用“put()”方法。在这 20 个线程中,当一个线程正在执行时,其余 19 个线程将处于 BLOCKED 状态。只有在初始线程退出 'get()'、'put()' 方法后,剩余线程才能继续前进。因此,性能将显着下降。
为了确认这种行为,我们执行了上述程序并捕获了线程转储并使用fastThread(线程转储分析工具)对其进行了分析。工具生成了这个有趣的分析报告。以下是报告的摘录,显示了 BLOCKED 线程的传递依赖图
图:Hashtable 上阻塞的线程(由fastThread生成)
报告显示有 19 个线程处于 BLOCKED 状态,而其中一个线程(即“Thread-15”)正在执行 Hashtable 中的“get()”方法。因此,只有在 'Thread-15' 退出 'get()' 方法后,其他线程才能前进并执行 'get()'、'put()' 方法。这将导致应用程序性能显着下降。
结论
因此,如果你需要使用 map 数据结构,你可以考虑使用 ConcurrentHashMap,它提供了与 HashMap 类似的性能特征,但同时提供了类似 Hashtable 的线程安全行为。
原文地址:https://blog.fastthread.io/2022/04/22/java-hashtable-hashmap-concurrenthashmap-performance-impact/
原文作者:fastthread团队
原文链接:https://blog.fastthread.io/2022/04/22/java-hashtable-hashmap-concurrenthashmap-performance-impact/