Предыдущая хэш-карта будет восстановлена или все еще будет использоваться, если реконструкция произошла?
Это все та же хеш-карта, просто реконструируется внутреннее хранилище. После реконструкции старый массив бакетов больше не нужен и может быть собран.
Обновление: внутри HashMap
есть Node<K,V>[] table
. При изменении размера создается новый массив, элементы перемещаются, а затем table
заменяется новым массивом. После этой операции сама карта больше не будет ссылаться на старый массив, поэтому, если нет других ссылок (что маловероятно из-за того, что table
является частным пакетом), она подходит для gc.
так как нам нужна хеш-карта большего размера, будет ли изменена хэш-функция?
Нет, хэш-функция не изменится. Как правило, это не зависит от количества сегментов, но сгенерированный хэш будет скорректирован для получения правильного сегмента (например, путем применения модуля)
Обновление: HashMap
вычисляет индекс корзины следующим образом: (size - 1) & hash
, hash
— это возвращаемое значение метода hashCode()
ключа, которое не зависит от самой карты.
Для ConcurrentHashMap, что, если один поток выполняет вставку (конечно, эта операция вставки привела к перестроению), а другой поток читает? Например, он будет читать из старой хэш-карты или из новой хэш-карты?
Здесь мне придется угадать (я посмотрю код позже), но я предполагаю, что пока потоки читают из старых сегментов, они все еще будут использоваться и будут освобождены позже.
Обновление: я бегло просмотрел исходники ConcurrentHashMap
и обнаружил ссылки на текущий table
, который используется get()
, и возможный nextTable
, который является целью для операций изменения размера. Во время изменения размера элементы переносятся в nextTable
, а в конце table
устанавливаются в nextTable
, эффективно переключая таблицы.
Это означает, что при изменении размера старая таблица все еще читается и в какой-то момент заменяется. Во время операций вставки могут быть некоторые блокировки, например. с помощью синхронизированных блоков, особенно если изменение размера необходимо или уже выполняется.
Документация также намекает на это:
Хэш-таблица, поддерживающая полный параллелизм извлечения и высокий ожидаемый параллелизм для обновлений.
Это означает, что get
не будет блокироваться, но put
, remove
и т. д. могут заблокироваться в какой-то момент.
person
Thomas
schedule
13.11.2014