Подтвердить что ты не робот

Разница между Hashtable и Collections.synchronizedMap(HashMap)

Насколько я знаю, java.util.Hashtable синхронизирует каждый метод в java.util.Map интерфейс, а Collections.synchronizedMap(hash_map) возвращает объект-оболочку, содержащий синхронизированные методы делегирования вызовов фактическому hash_map (исправьте меня, если я ошибаюсь).

У меня есть два вопроса:

  • Какая разница, чтобы синхронизировать каждый метод и иметь класс-оболочку? Каковы сценарии выбора одного над другим?

  • Что происходит, когда мы делаем Collections.synchronizedMap(hash_table)? Будет ли это равным простому использованию обычного java.util.Hashtable?

4b9b3361

Ответ 1

Вот ответы, которые я получил от небольшого (надеюсь, правильного) исследования:

  • Оба обеспечивают такую ​​же степень синхронизации. Если вы должны были обернуть Hashtable через Collections.synchronized, у вас будет такая же степень, но с другим избыточным уровнем синхронизации.

  • Основное отличие между Hashtable и Collections.synchronizedMap(HashMap) больше на уровне API. Поскольку Hashtable является частью устаревшего кода Java, вы увидите, что API Hashtable расширен для реализации интерфейса Map, чтобы стать частью структуры коллекций Java. Это означает, что если вы должны были обернуть Hashtable через Collections.synchronizedMap(), API завернутого Hashtable будет ограничен API Map. Поэтому, если API Hashtable включен в ваше определение поведения , то он явно изменен/ограничен.

Ответ 2

Еще одно отличие, которое я могу найти при реализации обоих классов, следующее:

• Класс Hashtable имеет все свои методы синхронизации, т.е. блокировка выполняется на уровне метода, и, следовательно, можно сказать, что мьютекс всегда на объекте Hashtable (this).

• Метод Collections.synchronizedMap(Map) возвращает экземпляр SynchronizedMap, который является внутренним классом класса Collections. Этот класс имеет все свои методы в блоке Synchronized с мьютексом. Здесь разница в мьютексе. Внутренний класс SynchronizedMap имеет два конструктора, один из которых принимает только Map в качестве аргумента, а другой, который принимает в качестве аргумента Map и Object (mutex). По умолчанию, если использовать первый конструктор для передачи только a Map, this используется как мьютекс. Хотя разработчику разрешено передавать еще один объект мьютекса в качестве второго аргумента, по которому блокировка методов Map будет только на этом Object и, следовательно, менее ограничительна, чем Hashtable.

• Следовательно, Hashtable использует синхронизацию уровня метода, но Collections.synchronizedMap(Map) обеспечивает гибкость блокировки разработчика при предоставленном мьютексе с блоком Synchronized.

Ответ 3

Первый класс ассоциативной коллекции появится в классе Java библиотека была Hashtable, которая была частью JDK 1.0. Hashtable предоставлен простой в использовании, потокобезопасной, ассоциативной возможности карты, и это было конечно удобный. Тем не менее, безопасность потока достигла цены - Синхронизированы все методы Hashtable. В то время, без синхронизация имела измеримую стоимость исполнения. Преемник Hashtable, HashMap, который появился как часть Коллекций в JDK 1.2, направленной на обеспечение безопасности потоков путем предоставления несинхронизированный базовый класс и синхронизированную обертку, Collections.synchronizedMap. Разделение базовой функциональности от система Collections.synchronizedMap для обеспечения безопасности потоков позволила пользователям, которые нуждались в синхронизация, чтобы иметь его, но пользователям, которые не нуждались в нем, не было заплатить за это.

Простой подход к синхронизации, сделанный как Hashtable, так и synchronizedMap - синхронизация каждого метода на Hashtable или синхронизированный объект оболочки оболочки - имеет два основных недостатка. Это является препятствием для масштабируемости, поскольку только один поток может получить доступ хэш-таблицу за раз. В то же время этого недостаточно обеспечивают истинную безопасность резьбы, поскольку многие общие составные операции по-прежнему требуется дополнительная синхронизация. Хотя простые операции такие поскольку get() и put() могут безопасно дополняться без дополнительных синхронизации, существует несколько общих последовательностей операций, таких как итерация или put-if-absent, которые по-прежнему требуют внешних синхронизация, чтобы избежать расследований данных.

Следующая ссылка является источником и имеет более подробную информацию: Параллельные классы коллекций

Ответ 4

Разница не все на очевидном уровне API, и на уровне реализации есть много тонкостей. Например, Hashtable не поддерживает HashMap расширенный пересчет хэш-кодов поставляемых ключей, что уменьшает хеш-коллизии. С другой стороны, Hashtable#hashCode() позволяет избежать бесконечной рекурсии для самореферентных хэш-таблиц, чтобы позволить "некоторым апплетам с 1,1-й эрой с самореферентными хеш-таблицами работать".

В целом, однако, нельзя рассчитывать на Hashtable получение каких-либо дальнейших улучшений или уточнений за пределами базовой корректности и обратной совместимости. Это считается реликвией глубокого прошлого Java.

Ответ 5

С риском указания очевидного (или просто неправильного) не разница, что

Оболочки синхронизации добавляют автоматическую синхронизацию (безопасность потока) к произвольной коллекции

http://docs.oracle.com/javase/tutorial/collections/implementations/wrapper.html и продолжает говорить

Коллекция, созданная таким образом, каждый бит как поточно-безопасный, как обычно синхронизированный набор, такой как вектор.

Вам может понравиться эта тема для вопросов, касающихся HashMaps и concurrency - Hashmap concurrency issue (или вы, возможно, очень хорошо их знаете), Хорошим примером является:

Условия, которые вы описываете, не будут удовлетворены HashMap. поскольку процесс обновления карты не является атомарным, вы можете столкнуться с картой в недопустимом состоянии. Несколько записей могут оставить его в поврежденном состоянии государство. ConcurrentHashMap (1.5 или новее) делает то, что вы хотите.

fooobar.com/info/154975/...

Я предполагаю, что в терминах "когда я должен использовать это" я хотел бы использовать синхронизированную коллекцию, где требуется concurrency, иначе вы можете создавать больше работы для себя (см. ниже).

С точки зрения изменения поведения

Если используется явный итератор, следует вызвать метод итератора изнутри синхронизированного блока. Несоблюдение этого совета может приводят к недетерминированному поведению

Есть больше последствий использования синхронизации, предоставляемой на предоставляемой (Oracle) ссылке.