Почему класс Java Vector (и Stack) считается устаревшим или устаревшим?

Почему Java Vector считается устаревшим классом, устаревшим или устаревшим?

не является ли его использование допустимым при работе с параллелизмом?

и если я не хочу вручную синхронизировать объекты и просто хочу использовать потокобезопасную коллекцию без необходимости делать свежие копии базового массива (как CopyOnWriteArrayList делает), то это нормально, чтобы использовать Vector?

насчет Stack, который является подклассом Vector, что я должен использовать вместо него?

5 ответов


Vector синхронизирует на каждой индивидуальной деятельности. Это почти никогда не то, что вы хотите сделать.

как правило, вы хотите синхронизировать вся последовательность операций. Синхронизация отдельных операций является менее безопасной (если вы выполняете итерацию по Vector, например, вам все равно нужно вынуть блокировку, чтобы избежать кого-либо еще, меняющего коллекцию одновременно, что вызовет ConcurrentModificationException в итерационном потоке), но и медленнее (зачем вынимать блокировку неоднократно, когда одного раза будет достаточно)?

конечно, он также имеет накладные расходы на блокировку, даже если вам это не нужно.

в принципе, это очень ошибочный подход к синхронизации в большинстве ситуаций. As Мистер Брайан Хенк указал, вы можете украсить коллекцию, используя такие вызовы, как Collections.synchronizedList


вектор был частью 1.0-оригинальная реализация имел два недостатка:

1. Именование: векторы-это просто списки, к которым можно получить доступ как к массивам, поэтому он должен был называться ArrayList (который является заменой коллекций Java 1.2 для Vector).

2. Параллелизм: все get(), set() методы synchronized, поэтому вы не можете иметь мелкозернистый контроль над синхронизацией.

там не так много разница между ArrayList и Vector, но вы должны использовать ArrayList.

из документа API.

начиная с платформы Java 2 v1.2, это класс был модифицирован для реализации Интерфейс списка, делая его членом платформы наборов Java. В отличие от новые реализации коллекции, Вектор синхронизации.


помимо уже заявленных ответов об использовании Vector, Vector также имеет кучу методов вокруг перечисления и извлечения элементов, которые отличаются от интерфейса списка, и разработчики (особенно те, кто изучил Java до 1.2) могут использовать их, если они находятся в коде. Хотя перечисления быстрее, они не проверяют, была ли коллекция изменена во время итерации, что может вызвать проблемы, и учитывая, что вектор может быть выбран для его синхронизации - с сопутствующий доступ из нескольких потоков, это делает его особенно пагубной проблемой. Использование этих методов также связывает много кода с вектором, так что заменить его другой реализацией списка будет непросто.


можно использовать synchronizedCollection/List метод on java.util.Collection чтобы получить потокобезопасную коллекцию из не потокобезопасной.


java.util.Stack наследует накладные расходы синхронизации java.util.Vector, который, как правило, не оправдано.

он наследует много больше. Дело в том, что java.util.Stack extends java.util.Vector является ошибкой в объектно-ориентированном дизайне. Пуристы заметят, что он также предлагает множество методов за пределами операций, традиционно связанных со стеком (а именно: push, pop, peek, size). Это также можно сделать search, elementAt, setElementAt, remove, и многие другие операции произвольного доступа. Это в основном до пользователя, чтобы воздержаться от использования операций без стека Stack.

для этих причин представления и дизайна ООП,JavaDoc для java.util.Stack рекомендует ArrayDeque как естественная замена. (Deque-это больше, чем стек, но, по крайней мере, он ограничен манипулированием двумя концами, а не предлагает случайный доступ ко всему.)