Единственное, о чем я могу думать, это может объяснить проблему, если ваши объекты очень большие и у вас почти не осталось кучи.Когда это происходит, JVM может останавливаться на все более длительный период времени, пытаясь очиститься.В Java 6 он пытается обнаружить это до того, как он станет действительно плохим, и выдает OutOfMemoryError (до того, как он полностью иссякнет, но не смог очистить много) Java 5.0 не делает этого.
Это объясняет, почемувещи снова ускоряются, когда вы отбрасываете несколько объектов.
Стандартная реализация HashMap ограничена примерно 750 миллионами записей (в зависимости от того, как вы ее используете, например, средняя загрузка). Максимальная емкость, которую он может иметьравен 2 ^ 30 (один миллиард) и с коэффициентом загрузки 0,75f (~ 750 м записей) он будет пытаться увеличить базовый массив, чтобы удвоить этот размер, что он не может сделать.(Максимальный размер: Integer.MAX_VALUE)
Вы можете использовать LinkedHashMap в качестве кэша, исключая запись "eldset" на основе правила, которое вы должны предоставить.
Однако, если только не HashMapсинхронизируется не будет блокировать.Если он потерпит неудачу, он выдаст исключение.
Единственный последовательный способ получить Карту для блокирования таким образом - это завести тупик.
Другой способ, которым это может случиться, - это если вы используете одну и ту же карту в двух потоках небезопасным способом.В этом случае поведение не определено, однако я видел, что оно вызывает проблемы в 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);
}
}
печатает следующее через 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