Вопрос

Я не уверен, что это правильный способ синхронизировать мой ArrayList.

У меня есть ArrayList in_queue который передается из registerInQueue функция.

ArrayList<Record> in_queue = null;

public void registerInQueue(ArrayList in_queue)
{
    this.in_queue = in_queue;
}

Теперь я пытаюсь это синхронизировать.Это синхронизирует мой in_queue правильно возражаете?

List<Record> in_queue_list = Collections.synchronizedList(in_queue);

synchronized (in_queue_list) {
    while (in_queue_list.size() > 0) {
        in_queue_list.remove(0);
    }
}
Это было полезно?

Решение

Вы синхронизируете дважды, что бессмысленно и, возможно, замедляет работу кода:изменения при переборе списка требуют синхронизации всей операции, которую вы выполняете с помощью synchronized (in_queue_list) Используя Collections.synchronizedList() является излишним в этом случае (он создает оболочку, которая синхронизирует отдельные операции).

Однако, поскольку вы полностью очищаете список, повторное удаление первого элемента - наихудший из возможных способов сделать это, так как для каждого элемента все последующие элементы должны быть скопированы, что делает эту операцию O (n ^ 2) ужасно медленной для больших списков.

Вместо этого просто позвоните clear() - никаких повторений не требуется.

Редактировать: Если вам нужна однометодная синхронизация Collections.synchronizedList() позже, значит, это правильный путь:

List<Record> in_queue_list = Collections.synchronizedList(in_queue);
in_queue_list.clear(); // synchronized implicitly, 

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

Другие советы

Глядя на ваш пример, я думаю, что ArrayBlockingQueue (или его братья и сестры) могут быть полезны. Они следят за синхронизацией для вас, поэтому потоки могут писать в очередь или просматривать / извлекать данные без дополнительной синхронизации с вашей стороны.

Это правильно и задокументировано.

http : //java.sun.com/javase/6/docs/api/java/util/Collections.html#synchronizedList (java.util.List)

Однако, чтобы очистить список, просто вызовите List.clear () .

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

Однако в Java существуют далеко идущие параллельные очереди, такие как ConcurrentLinkedQueue

Давайте возьмем обычный список (реализованный классом ArrayList) и сделаем его синхронизированным. Это показано в классе SynchronizedListExample.     Мы передаем методу Collections.synchronizedList новый ArrayList из строк. Метод возвращает синхронизированный список строк.     // Здесь находится класс SynchronizedArrayList

package com.mnas.technology.automation.utility;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.apache.log4j.Logger;
/**
* 
* @author manoj.kumar
* @email kumarmanoj.mtech@gmail.com
* 
*/
public class SynchronizedArrayList {
    static Logger log = Logger.getLogger(SynchronizedArrayList.class.getName());
    public static void main(String[] args) {    
        List<String> synchronizedList = Collections.synchronizedList(new ArrayList<String>());
        synchronizedList.add("Aditya");
        synchronizedList.add("Siddharth");
        synchronizedList.add("Manoj");
        // when iterating over a synchronized list, we need to synchronize access to the synchronized list
        synchronized (synchronizedList) {
            Iterator<String> iterator = synchronizedList.iterator();
            while (iterator.hasNext()) {
                log.info("Synchronized Array List Items: " + iterator.next());
            }
        }    
    }
}

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top