Почему Java Vector считается устаревшим классом, устаревшим или устаревшим?
Разве его использование не допустимо при работе с параллелизмом?
И если я не хочу вручную синхронизировать объекты и просто хочу использовать потокобезопасную коллекцию без необходимости делать свежие копии базового массива (как это CopyOnWriteArrayList
делается), то хорошо ли это использовать Vector
?
Как насчет того Stack
, что является подклассом Vector
, что я должен использовать вместо него?
Ответы:
Vector
синхронизируется на каждой отдельной операции. Это почти никогда не то, что вы хотите сделать.Как правило, вы хотите синхронизировать всю последовательность операций. Синхронизация отдельных операций и менее безопасна (например, если вы выполняете итерацию по a
Vector
, вам все равно нужно снять блокировку, чтобы никто не изменил коллекцию в одно и то же время, что могло бы вызвать aConcurrentModificationException
в итерирующем потоке), но также и медленнее ( зачем вынимать блокировку повторно, когда одного раза будет достаточно)?Конечно, он также имеет накладные расходы на блокировку, даже когда вам это не нужно.
По сути, это очень некорректный подход к синхронизации в большинстве ситуаций. Как отметил г-н Брайан Хенк , вы можете декорировать коллекцию, используя такие вызовы, как
Collections.synchronizedList
- тот факт, чтоVector
комбинация реализации коллекции «массив с измененным размером» и бита «синхронизировать каждую операцию» является еще одним примером плохого дизайна; декоративный подход дает более четкое разделение проблем.Что касается
Stack
эквивалента - я бы посмотрел наDeque
/ArrayDeque
для начала.источник
Vector был частью 1.0 - оригинальная реализация имела два недостатка:
1. Наименование: векторы на самом деле представляют собой просто списки, к которым можно обращаться как к массивам, поэтому их следует вызывать
ArrayList
(что является заменой коллекций Java 1.2Vector
).2. Параллельность: Все из
get()
,set()
методыsynchronized
, так что вы не можете иметь мелкозернистый контроль над синхронизацией.Нет большой разницы между
ArrayList
иVector
, но вы должны использоватьArrayList
.Из API док.
источник
ArrayList
,LinkedList
и т.д., все из которых реализует интерфейсList
, так что если вы хотите использоватьList
методы , не зная , что основная реализация на самом деле вы можете просто взять вList
качестве параметра методов и т.д. То же самое относится к реализаторамMap
и так далее. Между тем, в C ++ естьstd::array
класс, который является просто заменой массивов статической длины в стиле C на основе шаблонов.Помимо уже заявленных ответов об использовании Vector, в Vector также есть несколько методов для перечисления и извлечения элементов, которые отличаются от интерфейса List, и разработчики (особенно те, кто изучал Java до 1.2) могут использовать их, если они находятся в код. Несмотря на то, что перечисления выполняются быстрее, они не проверяют, была ли коллекция изменена во время итерации, что может вызвать проблемы, и учитывая, что Vector может быть выбран для его синхронизации - с помощью сопутствующего доступа из нескольких потоков, это делает ее особенно пагубной проблемой. Использование этих методов также связывает большую часть кода с Vector, так что будет нелегко заменить его другой реализацией List.
источник
Вы можете использовать synchronizedCollection / List метод в
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 - это больше, чем стек, но, по крайней мере, он ограничен манипулированием двумя концами, а не предлагает произвольный доступ ко всему.)источник