Цей код видасть виняток паралельної модифікації, якщо список змінено у doSomething (). Чи можна цього уникнути, вклавши код у якийсь синхронізований блок?
List l = Collections.synchronizedList(new ArrayList());
// normal iteration -- can throw ConcurrentModificationException
// may require external synchronization
for (Iterator i=list.iterator(); i.hasNext(); ) {
doSomething(i.next());
}
Відповіді:
7 для відповіді № 1якщо ви вилучаєте елемент зі списку, ви можете зробити це, зателефонувавши
iterator.remove()
замістьlist.remove(iterator.next())
якщо ви додаєте елемент - ну, створіть копію повторного списку і додайте його туди
якщо наведений вище фрагмент коду є частиною того самого методу, то вам не потрібен синхронізований список або синхронізовані блоки - жоден інший потік не може отримати доступ до локального списку.
3 для відповіді № 2
ви може змінити a Collection
переглядаючи його, якщо ви робите це через Iterator
інтерфейс. Можна використовувати Iterator.remove()
для видалення елементів.
0 для відповіді № 3
Ви не можете змінити його під час ітерації. Синхронізація тут не допоможе.
EDIT: Я забув, що у ітератора є файл remove
метод. Тож можна видалити.
0 для відповіді № 4
Я погоджуюсь з іншими щодо Iterator
і remove()
.
Щодо синхронізації, я хотів додати, що синхронізація призначена для управління взаємодіями між різними нитками.
Для об’єкта характерно мати декількаметоди синхронізовані, і що один буде викликати інший. Тому дизайнери мови вирішили, що той самий потік не буде заблокований ним самим при синхронізації.
Також, задумавшись, це нитка заблокована, чекаючи на себе, у вас чудова голодування перспектива! ;-)
Отже, це відповідає на одне з ваших запитань: неможливо уникнути проблеми, синхронізуючи ваш код.
0 для відповіді № 5
Використовуйте CopyOnWriteArrayList
замість синхронізованого списку масивів
0 для відповіді № 6
List l = Collections.synchronizedList(new ArrayList());
synchronized(l) {
// normal iteration -- can throw ConcurrentModificationException
// may require external synchronization
for (Iterator i=list.iterator(); i.hasNext(); ) {
doSomething(i.next());
}
}