我一直在我的代码中使用一个HashMap对象进行一些性能检查,发现它减慢了在2000-2400个对象内部添加对象的速度.事实上,当它到达大约2400个物体时,它仍然被阻挡,并且不允许更多的条目.这种物体是否存在限制,当它们被保存在记忆中时,在它们被清空或被回收之前不会允许更多的条目?
非常感谢你.
我能想到的唯一可以解释问题的是你的对象是否非常大并且你几乎没有堆.当发生这种情况时,JVM可以在很长一段时间内停止尝试清理.在Java 6中,它尝试在它变得非常糟糕之前检测到它并抛出一个OutOfMemoryError(在它完全用完之前但是它无法清理很多)Java 5.0不会这样做.
它可以解释为什么当您丢弃一些对象时,事情会再次加速.
HashMap的标准实现限制在大约7.5亿条目(取决于您如何使用它,例如您的平均负载)它可以拥有的最大容量是2 ^ 30(10亿)并且负载因子为0.75f(~750m条目) )它会尝试增加底层数组,使其不能达到这个大小的两倍.(因为最大大小为Integer.MAX_VALUE)
您可以使用LinkedHashMap作为缓存,根据您必须提供的规则驱逐"eldset"条目.
但是,除非HashMap已同步,否则它将不会阻止.如果失败则会抛出异常.
使Map以这种方式阻止的唯一一致方法是出现死锁.
另一种方法是,如果您以不安全的方式在两个线程中使用相同的映射.在这种情况下,行为是未定义的,但是我已经看到它导致JVM中的问题(很少),甚至"挂起"所涉及的线程.即使是这种情况,我也希望它能够增加HashMap的默认加载因子,这将是3072(即4096*0.75),而不是你看到的值.
即使有一个糟糕的hashCode实现也无法解释这个问题.
static class BadHash {
@Override
public int hashCode() {
return 1;
}
}
public static void main(String... args) {
Map<BadHash, Boolean> map = new HashMap<BadHash, Boolean>();
for (int i = 0; i <= 100000; i++) {
if (i % 10000 == 0) System.out.println(i + ": " + new Date());
map.put(new BadHash(), true);
}
}
Run Code Online (Sandbox Code Playgroud)
在14秒内打印以下内容.
0: Mon Sep 26 12:23:39 BST 2011
10000: Mon Sep 26 12:23:39 BST 2011
20000: Mon Sep 26 12:23:39 BST 2011
30000: Mon Sep 26 12:23:40 BST 2011
40000: Mon Sep 26 12:23:41 BST 2011
50000: Mon Sep 26 12:23:42 BST 2011
60000: Mon Sep 26 12:23:44 BST 2011
70000: Mon Sep 26 12:23:46 BST 2011
80000: Mon Sep 26 12:23:48 BST 2011
90000: Mon Sep 26 12:23:51 BST 2011
100000: Mon Sep 26 12:23:53 BST 2011
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
204 次 |
| 最近记录: |