Подтвердить что ты не робот

Синхронизированный список Java

У меня есть список предварительно заполненных массивов. И у меня есть несколько потоков, которые будут удалять элементы из списка массивов. Каждый поток вызывает метод удаления ниже и удаляет один элемент из списка. Предоставляет ли следующий код мне последовательное поведение?

ArrayList<String> list = Collections.synchronizedList(new ArrayList<String>());

void remove(String item)
{
     do something; (doesn't work on the list)
     list.remove(item);
}

Спасибо!

4b9b3361

Ответ 1

Да, просто будьте осторожны, если вы также выполняете итерирование по списку, потому что в этом случае вам нужно будет синхронизировать его. Из Javadoc:

Обязательно, чтобы пользователь вручную выполнял синхронизацию по возвращенному списку при итерации по нему:

List list = Collections.synchronizedList(new ArrayList());
    ...
synchronized (list) {
    Iterator i = list.iterator(); // Must be in synchronized block
    while (i.hasNext())
        foo(i.next());
}

Или вы можете использовать CopyOnWriteArrayList, который медленнее для записи, но не имеет этой проблемы.

Ответ 2

Это должно быть хорошо, если вы не требуете, чтобы метод "remove" был атомарным.

Другими словами, если "сделать что-то" проверяет, что элемент отображается более одного раза в списке, например, возможно, что результат этой проверки будет неправильным к моменту достижения следующей строки.

Кроме того, убедитесь, что вы выполняете синхронизацию в списке:

synchronized(list) {
    for (Object o : list) {}
}

Как упоминал Питер Лоури, CopyOnWriteArrayList может облегчить вашу жизнь и обеспечить лучшую производительность в высококонкурентной среде.

Ответ 3

От Collections#synchronizedList(List) javadoc

Возвращает синхронизированный (потокобезопасный) список, поддерживаемый указанным список. Чтобы гарантировать последовательный доступ, важно, чтобы все доступ к списку поддержки выполняется через возвращенный список... Крайне важно, чтобы пользователь вручную синхронизировал в возвращенном списке при повторении по нему. Несоблюдение этого совета может привести к детерминированному поведению.

Ответ 4

У вас могут быть две проблемы с перечнями:
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) Вторая проблема может быть многопоточной средой. Как упоминалось выше, вы можете использовать синхронизированный (список), чтобы избежать исключений.

Ответ 5

Это даст последовательное поведение для операций добавления/удаления. Но при повторении вы должны явно синхронизироваться. Обратитесь к этой ссылке

Ответ 6

Да, он будет работать нормально, поскольку у вас есть 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);
    }

Ответ 7

synchronized(list) {
    for (Object o : list) {}
}