Должен ли я использовать старую синхронизированную коллекцию Vector, ArrayList с синхронизированным доступом или Collections.synchronizedList или какое-либо другое решение для одновременного доступа?
Я не вижу свой вопрос в разделе "Вопросы, относящиеся к теме", и не в моем поиске (Сделать потоки потолочными? не то же самое).
В последнее время мне пришлось сделать отдельные модульные тесты в графических интерфейсах нашего приложения (в основном с помощью API для создания фреймов, добавления объектов и т.д.). Поскольку эти операции называются намного быстрее, чем пользователем, он показал ряд проблем с методами, пытающимися получить доступ к ресурсам, которые еще не были созданы или уже удалены.
Конкретная проблема, возникающая в EDT, произошла в результате перехода связанного списка представлений при изменении ее в другом потоке (получение ConcurrentModificationException среди других проблем). Не спрашивайте меня, почему это был связанный список, а не простой список массивов (даже меньше, чем у нас вообще 0 или 1 вид внутри...), поэтому я взял более общий ArrayList в моем вопросе (поскольку он имеет старший кузен).
Во всяком случае, не очень знакомый с проблемами concurrency, я искал немного информации и задавался вопросом, что выбрать между старым (и, возможно, устаревшим) Vector (который имеет синхронизированные операции по дизайну), ArrayList с synchronized (myList) { }
вокруг критических секций (операции добавления/удаления/перемещения) или использования списка, возвращенного Collections.synchronizedList(даже не уверен, как использовать последний).
Я, наконец, выбрал второй вариант, потому что другая ошибка дизайна заключалась в том, чтобы разоблачить объект (метод getViewList()...) вместо предоставления механизмов для его использования.
Но каковы плюсы и минусы других подходов?
[EDIT] Много хороших советов здесь, трудно выбрать. Я выберу более подробные и обеспечивающие ссылки/пищу для размышлений...:-) Мне тоже нравится Даррон.
Подводя итог:
- Как я и предполагал, Vector (и его злой близнец, Hashtable, вероятно,), в значительной степени устарел, я видел, как люди, рассказывающие о своем старом дизайне, не так хороши, как новые коллекции ", за пределами медленности синхронизации, вызванной даже в однопоточная среда. Если мы его сохраним, это в основном потому, что старые библиотеки (и части Java API) все еще используют его.
- В отличие от того, что я думал, Collections.synchronizedXxxx не являются более современными, чем Vector (они, похоже, современны для Collections, то есть Java 1.2!) и не лучше, на самом деле. Хорошо знать. Короче говоря, я должен избегать их также.
- Ручная синхронизация, похоже, является хорошим решением в конце концов. Могут быть проблемы с производительностью, но в моем случае это не критично: операции, выполняемые с действиями пользователя, небольшая коллекция, не частое использование.
- java.util.concurrent пакет стоит иметь в виду, особенно методы CopyOnWrite.
Надеюсь, у меня все получилось...: -)