2012-01-16 3 views
35

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

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

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

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

+0

Возможный дубликат [Различия между HashMap и Hashtable?] (Http://stackoverflow.com/questions/40471/differences-between-hashmap-and-hashtable) –

+13

Это не дубликат * этого * вопроса. Это сравнивает синхронизированную оболочку по HashMap (или HashTable) с помощью HashTable. –

+0

Мне было бы интересно узнать, есть ли различия в производительности, на которые не отвечает ни один из текущих ответов. Вызов методов 'Collections.synchronizedMap' с помощью переменной типа Map означает, что перед тем, как перейти к реализации, есть два виртуальных вызова интерфейса, тогда как с Hashtable существует не более 1 виртуального вызова, и вы можете объявить свою переменную как тип Hashtable напрямую, и делать это с помощью 0 виртуальных вызовов. Но, возможно, HashMap отличается другими способами, которые ускоряют работу в целом. – Boann

ответ

13

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

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

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

1

Рискуя констатировал очевидное (или быть просто неправильно) не является той разницей, что

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

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

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

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

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

https://stackoverflow.com/a/1003071/201648

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

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

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

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

4

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

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

Следующая ссылка является источником и имеет больше информации: Concurrent Collections Classes

+1

Второй абзац гласит, что 'Hashtable' и' synchronizedMap' - это одно и то же. Это означает, что мы вообще не ответили на вопрос: в чем их отличие? – Pacerier

+0

прочитал ответ от @mankadnandan –

3

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

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

45

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

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

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

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

+2

Какой красивый ответ, подчеркивающий то, что осталось нетронутым, иначе в ответах на отдых. +1 –

+3

Дополнительный конструктор и синхронизация на уровне блока (в отличие от уровня метода для HashTable) - это ключи. –

+3

Это действительно интересная информация, но внутренний класс SynchronizedMap является закрытым, и нет статического метода, соответствующего версии конструктора, который принимает объект mutex в качестве аргумента, поэтому разработчик не может действительно предоставить пользовательский мьютекс, не так ли? – CarLuva

Смежные вопросы