Список синхронизированных Java
У меня есть предварительно заполненный список массивов. И у меня есть несколько потоков, которые будут удалять элементы из списка выбора. Каждый поток вызывает метод remove ниже и удаляет один элемент из списка. Следующий код дает мне последовательное поведение ?
ArrayList<String> list = Collections.synchronizedList(new ArrayList<String>());
void remove(String item)
{
do something; (doesn't work on the list)
list.remove(item);
}
спасибо!
7 ответов:
да, просто будьте осторожны, если вы также повторяете список, потому что в этом случае вам нужно будет синхронизировать его. Из документация:
необходимо, чтобы пользователь вручную синхронизировал возвращенный список при повторении его:
List list = Collections.synchronizedList(new ArrayList()); ... synchronized (list) { Iterator i = list.iterator(); // Must be in synchronized block while (i.hasNext()) foo(i.next()); }или, вы можете использовать
CopyOnWriteArrayListкоторый медленнее для записи, но не имеет этой проблемы.
Это должно быть хорошо, если вам не требуется, чтобы метод "remove" был атомарным.
кроме того, убедитесь, что вы синхронизируете в списке при повторении:
synchronized(list) { for (Object o : list) {} }Как отметил Петр Lawrey, CopyOnWriteArrayList может сделать вашу жизнь более легкая и может обеспечить более лучшее представление в сильно одновременной окружающей среде.
С
Collections#synchronizedList(List)документациявозвращает синхронизированный (потокобезопасный) список, поддерживаемый указанным список. Чтобы гарантировать последовательный доступ, важно, чтобы все доступ к списку резервного копирования осуществляется через возвращенный список ... Необходимо, чтобы пользователь вручную синхронизировал возвращенный список при его повторении. Несоблюдение этого совета может привести к недетерминированному поведению.
вы можете иметь 2 различных проблемы со списками:
1) Если вы делаете модификацию в итерации, даже если в среде моно-потока, у вас будет ConcurrentModificationException, как в следующем примере :List<String> list = new ArrayList<String>(); for (int i=0;i<5;i++) list.add("Hello "+i); for(String msg:list) list.remove(msg);поэтому, чтобы избежать этой проблемы, вы можете сделать :
for(int i=list.size()-1;i>=0;i--) list.remove(i);2) второй проблемой может быть многопоточная среда. Как уже упоминалось выше, вы можете использовать synchronized(list), чтобы избежать исключений.
Это даст последовательное поведение для операций добавления/удаления. Но во время итерации вы должны явно синхронизироваться. см. ссылку
Да, он будет работать нормально, как у вас
synchronizedсписок . Я бы предложил вам использоватьCopyOnWriteArrayList.CopyOnWriteArrayList<String> cpList=new CopyOnWriteArrayList<String>(new ArrayList<String>()); void remove(String item) { do something; (doesn't work on the list) cpList..remove(item); }