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

Правильный способ синхронизации ArrayList в java

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

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

ArrayList<Record> in_queue = null;

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

Теперь я пытаюсь синхронизировать его. Является ли это sychronizing мой объект 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);
    }
}
4b9b3361

Ответ 1

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

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

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

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

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

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

Ответ 2

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

Ответ 4

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

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

Ответ 5

Возьмем обычный список (реализуемый классом ArrayList) и сделаем его синхронизированным. Это показано в классе SynchronizedListExample.   Мы передаем метод Collections.synchronizedList новый ArrayList of Strings. Метод возвращает синхронизированный список строк.   // Вот класс 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 [email protected]
* 
*/
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. В общем случае итерация по синхронизированной коллекции должна выполняться в синхронизированном блоке