Используйте Hashtable, Vector или HashMap или ArrayList в Java

Один из мемов, который вызывает стресс при разработке Java, - это всегда использовать ArrayList вместо Vector. Vector устарел. Это может быть правдой, но преимущество Vector и Hashtable в том, что они синхронизированы.

Я работаю с сильно ориентированным на параллелизм приложением, не будет ли пользы от использования синхронизируемых объектов, таких как Vector? Кажется, у них есть свое место?

Vector еще не объявлен устаревшим.

Champ 12.09.2010 12:44

В последней версии Java 6 с Netbeans утверждается, что Vector устарел ... Должно быть, это было объявлено где-то еще некоторое время назад, потому что у меня есть заметки за несколько месяцев о необходимости найти ему замену и проблемы с некоторыми не- устаревшие классы все еще нуждаются в этом.

Brian Knoblauch 23.09.2010 15:32
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
13
2
32 581
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

Ответ принят как подходящий

Проблема с Vector и Hashtable в том, что они синхронизируются только локально. Они не будут ломаться (как в случае поврежденных данных) в параллельном приложении, однако из-за локальной синхронизации (например, get синхронизируется, но только до тех пор, пока get не вернется), вы все равно захотите выполнить свою собственную синхронизацию в таких ситуациях. как итерация по содержанию. Теперь даже вашему методу put требуется дополнительная синхронизация для взаимодействия с синхронизацией итераций, и вы получаете ситуацию, когда ваша Hashtable / Vector синхронизируется дважды.

По ошибке удалил свой комментарий. Вы ошибаетесь, что put () требует дополнительной синхронизации; итератор () будет просто синхронизироваться с самим вектором, который выполняет мьютексы со всей синхронизацией в векторе. В этом они идентичны Collections.synchronizedList ().

Lawrence Dol 18.01.2009 08:05

Если вы используете свой итератор в цикле for, содержимое цикла for не будет синхронизироваться, и ваш итератор, вероятно, вызовет исключение одновременной модификации, если кто-то использует put между 'next'. Следовательно, вам нужна дополнительная синхронизация (конечно, есть и другие варианты).

falstro 19.01.2009 10:52

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

Lawrence Dol 19.01.2009 23:51

Ах да, я понимаю, что вы имеете в виду, вы, конечно, правы. Думаю, я немного поспешил выразить тот факт, что вам, вероятно, понадобится отдельная схема синхронизации, не связанная с одним массивом / картой, и поэтому внутренняя синхронизация будет чистыми накладными расходами.

falstro 20.01.2009 10:46

Если вам нужен синхронизированный ArrayList или HashMap, вы можете их обернуть.

List list = Collections.synchronizedList(new ArrayList(...));
Map m = Collections.synchronizedMap(new HashMap(...));

Лично я считаю, что "синхронизированные" методы в этих коллекциях не очень полезны в тяжелом многопоточном коде. Есть несколько более новых коллекций, которые помогают намного больше, но в основном я обнаруживаю, что создаю свои собственные синхронизирующие объекты и синхронизирую их вокруг них или использую новые блокировки в java.util.concurrent

У синхронизации есть свое место, но это не единственное различие между Vector и ArrayList. Vector увеличивает свой внутренний массив хранения на фиксированную величину каждый раз, когда он превышает свою емкость, в то время как ArrayList увеличивает его на фиксированный коэффициент, что обычно является гораздо лучшим подходом (поскольку он дает амортизированная стоимость O (1) для добавления элемента).

Также обратите внимание, что Collections.synchronizedList() можно использовать для создания синхронизированного представления в любой реализации List, поэтому вам не нужно быть привязанным к характеристикам Vector (например, вам может понадобиться синхронизированный LinkedList).

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

Wim Coenen 17.01.2009 21:24

Похоже, я забыл об этом!

Joachim Sauer 17.01.2009 21:28

Вы можете использовать статические методы коллекций для преобразования списка или карты в синхронизированную версию: http://java.sun.com/j2se/1.4.2/docs/api/java/util/Collections.html#synchronizedList(java.util.List)

Обычно вам нужно заблокировать больше, чем отдельный вызов списка или карты.

Мне кажется, что единственные случаи, когда вам потребуется, чтобы сама коллекция была потокобезопасной, это:

  • Если Коллекция видна извне класса (общедоступная или по умолчанию)
  • Если вы возвращаете дескриптор коллекции из метода
  • Если коллекция является статическим членом вашего класса

Все это, вероятно, плохие идеи с точки зрения дизайна.

Лучшим подходом было бы сделать саму коллекцию частной или защищенной и получить к ней доступ с помощью синхронизированных методов. В случае статического члена, если вам нужно это сделать, синглтон будет лучшим способом.

ConcurrentHashMap - это намного быстрее, чем Hashtable. Это одновременный, а не просто синхронизировано. Он допускает сразу несколько читателей / писателей.

Однако такого «параллельного» списка массивов не существует. В зависимости от ваших потребностей, CopyOnWriteArrayList может быть или не быть тем, что вам нужно.

Другие вопросы по теме