【问题标题】:HashMap holding duplicate keysHashMap 持有重复键
【发布时间】:2017-07-11 08:44:44
【问题描述】:

在尝试HashMap 时,我发现了一些奇怪的东西。

运行 4 个线程,每个线程都尝试使用从 0 到 9999 的键放置 (key,value),值一个常量字符串。在所有线程完成后,map.size() 返回一个大于 10,000 的值。这怎么发生的?这是否意味着地图包含重复的键?

我在map.entrySet() 上进行了迭代,发现某些键的计数确实大于1。如果我在地图上为一个这样的键执行get(),将返回什么值。

这是我尝试过的代码

final HashMap<String, String> vals = new HashMap<>(16_383);
Runnable task = new Runnable() {
    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            vals.put(""+i, Thread.currentThread().getName());
        }
    }
};
Thread thread = new Thread(task, "a");
Thread thread1 = new Thread(task, "b");
Thread thread2 = new Thread(task, "c");
Thread thread3 = new Thread(task, "d");
thread.start();
thread1.start();
thread2.start();
thread3.start();
thread.join();
thread1.join();
thread2.join();
thread3.join();
System.out.println(Thread.currentThread().getName() + "vals "+ vals.size());
System.out.println(Thread.currentThread().getName() + "vals "+ vals.entrySet().size());
System.out.println(Thread.currentThread().getName() + "vals "+ vals.keySet().size());

【问题讨论】:

  • HashMap 不是线程安全的。
  • "如果我这样做会返回什么值..." 为什么不干脆看看呢?
  • @DM。我不认为测试在两次运行之间是可重复的,甚至可能在给定的运行中也是如此。

标签: java concurrency hashmap


【解决方案1】:

HashMap 不是线程安全的,正如链接文档中明确指出的那样。您提供了一个很好的例子来说明为什么会这样。是的,您正在输入重复的键,因为put 不会检查另一个线程是否将相同的键放入。这就是线程安全的意思。

检索行为是未定义的,因此它可以在该点返回它想要的任何值。它可能非常依赖于实现、平台甚至时间。

有几种解决方法。文档中建议的一个是

Map m = Collections.synchronizedMap(new HashMap(...));

另一种选择是使用专门为此目的设计的ConcurrentHashMap

【讨论】:

    猜你喜欢
    • 2013-02-26
    • 2023-03-19
    • 2021-10-15
    • 2016-07-10
    • 1970-01-01
    • 2018-02-06
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    相关资源
    最近更新 更多