Зачем нам нужны синхронизированные списки массивов, когда у нас уже есть векторы? - PullRequest
1 голос
/ 20 января 2010

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

Ответы [ 5 ]

15 голосов
/ 20 января 2010

Я думаю, что вы поняли это неправильно. ArrayList не синхронизирован, Vector равен .

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

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

4 голосов
/ 20 января 2010

ArrayList не синхронизируется через http://java.sun.com/javase/6/docs/api/java/util/ArrayList.html

3 голосов
/ 20 января 2010

ArrayList не синхронизируется из коробки.

Реализация массива изменяемого размера Список интерфейса. Реализует все необязательные операции со списком и разрешения все элементы, включая ноль. В дополнение к реализации списка интерфейс, этот класс предоставляет методы манипулировать размером массива который используется внутри для хранения список. (Этот класс примерно эквивалентно Vector, за исключением того, что оно не синхронизирован.)

Это позволяет избежать некоторых проблем с производительностью в ситуациях, когда вы знаете, что вам не понадобится безопасность потоков (например, полностью инкапсулированные личные данные). Однако и у ArrayList, и у Vector есть проблемы при использовании итераторов над ними: при итерации по любому типу коллекции, если данные добавляются или удаляются, вы выбросите исключение ConcurrentModificationException :

Обратите внимание, что эта реализация не синхронизированы. Если несколько потоков получить доступ к экземпляру ArrayList одновременно, и по крайней мере один из темы изменяет список структурно он должен быть синхронизирован внешне. (Структурная модификация любая операция, которая добавляет или удаляет один или несколько элементов, или явно изменяет размер резервного массива; просто установка значения элемента не структурная модификация.) Это обычно достигается синхронизация на некотором объекте, который естественно инкапсулирует список. Если нет такой объект существует, список должен быть "завернутый" с помощью Метод Collections.synchronizedList. Это лучше всего сделать во время создания, чтобы предотвратить случайные несинхронизированные доступ к списку:

Список списка = Collections.synchronizedList (новый ArrayList (...));

Итераторы, возвращаемые этим классом методы итератора и listIterator безотказный: если список структурно изменено в любое время после итератор создается, кроме как через собственное удаление итератора или добавить методы, итератор бросит ConcurrentModificationException. Таким образом, перед лицом одновременного модификация, итератор не работает быстро и чисто, а не риск произвольный, недетерминированный поведение в неопределенное время в будущее.

Обратите внимание, что отказоустойчивое поведение итератор не может быть гарантирован вообще говоря, невозможно сделать какие-либо жесткие гарантии в наличие несинхронизированного одновременного модификация. Отказоустойчивые итераторы бросить ConcurrentModificationException на основе максимальных усилий. Следовательно, это было бы неправильно написать программу, которая зависело от этого исключения для его правильность: безотказное поведение итераторы должны использоваться только для обнаруживать ошибки.

ArrayList имеет множество полезных ароматов, а Vector - нет. Мой личный фаворит - CopyOnWriteArrayList :

Потокобезопасный вариант ArrayList, в котором все мутационные операции (добавление, установка и т. Д.) Реализованы путем создания новой копии базового массива.

Обычно это слишком дорого, но может быть более эффективным, чем альтернативы, когда операции обхода значительно превосходят число мутаций, и полезно, когда вы не можете или не хотите синхронизировать обходы, но при этом необходимо исключить помехи между параллельными потоками. Метод итератора в стиле «снимок» использует ссылку на состояние массива в момент создания итератора. Этот массив никогда не изменяется в течение времени жизни итератора, поэтому вмешательство невозможно, и итератор гарантированно не генерирует исключение ConcurrentModificationException. Итератор не будет отражать добавления, удаления или изменения в списке с момента его создания. Операции изменения элементов на самих итераторах (удаление, установка и добавление) не поддерживаются. Эти методы генерируют исключение UnsupportedOperationException.

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

2 голосов
/ 20 января 2010

Что означает, что список массивов синхронизируется в Java?

Это означает, что потокобезопасен.

  • Векторы синхронизированы. Любой метод, который касается содержимого вектора, является потокобезопасным.
  • ArrayList, с другой стороны, не синхронизирован, что делает их не защищенными от потоков.
0 голосов
/ 20 января 2010

Я читаю ArrayList синхронизируется в Java ..

Но список массивов API говорит, что

Обратите внимание, что эта реализация не синхронизированы

Таким образом, вы используете ArrayList, когда уверены, что не будете иметь дело с параллелизмом. Использование Vector может быть излишним, и может привести к проблемам с производительностью.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...