作者:被盗不玩了 | 来源:互联网 | 2023-02-11 10:51
在尝试时HashMap
,我发现了一些奇怪的东西.
跑4个线程,每个线程尝试使用0到9999之间的键(键,值),值为常量字符串.完成所有线程后,map.size()
返回大于10,000的值.这怎么发生的?这是否意味着地图包含重复的键?
我重复了一遍map.entrySet()
,发现一些键的计数确实超过了1.如果我get()
在地图上为一个这样的键做了一个值,将返回什么值.
这是我试过的代码
final HashMap 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());
Mad Physicis..
5
HashMap
如链接文档中明确指出的那样,它不是线程安全的.你提供了一个很好的例子,说明为什么会这样.是的,你正在放入重复的密钥,因为put
没有检查另一个线程是否放入相同的密钥.这就是说它不是线程安全的.
检索行为未定义,因此它可以返回该点所需的任何值.它可能是非常实现,平台甚至是时间依赖的.
有几种解决方法.文档中建议的那个是
Map m = Collections.synchronizedMap(new HashMap(...));
另一个选择是使用ConcurrentHashMap
,它是为此目的明确设计的.
1> Mad Physicis..:
HashMap
如链接文档中明确指出的那样,它不是线程安全的.你提供了一个很好的例子,说明为什么会这样.是的,你正在放入重复的密钥,因为put
没有检查另一个线程是否放入相同的密钥.这就是说它不是线程安全的.
检索行为未定义,因此它可以返回该点所需的任何值.它可能是非常实现,平台甚至是时间依赖的.
有几种解决方法.文档中建议的那个是
Map m = Collections.synchronizedMap(new HashMap(...));
另一个选择是使用ConcurrentHashMap
,它是为此目的明确设计的.