maneira correta para sincronizar ArrayList em java
-
07-07-2019 - |
Pergunta
Eu não tenho certeza se essa é a maneira correta para sincronizar o meu ArrayList
.
Eu tenho um ArrayList
in_queue
que é passado a partir da função registerInQueue
.
ArrayList<Record> in_queue = null;
public void registerInQueue(ArrayList in_queue)
{
this.in_queue = in_queue;
}
Agora eu estou tentando sincronizá-lo. É este sychronizing meu objeto in_queue
corretamente?
List<Record> in_queue_list = Collections.synchronizedList(in_queue);
synchronized (in_queue_list) {
while (in_queue_list.size() > 0) {
in_queue_list.remove(0);
}
}
Solução
Você está sincronizando duas vezes, que é inútil e possivelmente retarda o código: mudanças durante a iteração sobre a necessidade lista um synchronnization ao longo de toda a operação, o que você está fazendo com synchronized (in_queue_list)
Usando Collections.synchronizedList()
é supérfluo nesse caso (que cria um wrapper que sincroniza operações individuais).
No entanto, desde que você está esvaziando a lista completamente, a remoção iterado do primeiro elemento é a pior maneira possível fazê-lo, sice para cada elemento de todos os elementos seguintes tem que ser copiado, tornando esta uma O (n ^ 2) operação -. terrivelmente lenta para listas maiores
Em vez disso, simplesmente chamar clear()
-. Sem iteração necessário
Editar:
Se você precisar a sincronização em um único método de Collections.synchronizedList()
mais tarde, então este é o caminho correto:
List<Record> in_queue_list = Collections.synchronizedList(in_queue);
in_queue_list.clear(); // synchronized implicitly,
Mas em muitos casos, a sincronização em um único método é insuficiente (por exemplo para todos iteração, ou quando você recebe um valor, fazer cálculos com base nele, e substituí-lo com o resultado). Nesse caso, você tem que usar a sincronização manual de qualquer maneira, então Collections.synchronizedList()
é apenas inútil sobrecarga adicional.
Outras dicas
Olhando para o seu exemplo, eu acho que ArrayBlockingQueue (ou seus irmãos) podem ser de uso. Eles cuidam da sincronização para você, então tópicos pode escrever para a fila ou espiada / tomar sem trabalho sincronização adicional de sua parte.
Isso é correto, e documentado:
http : //java.sun.com/javase/6/docs/api/java/util/Collections.html#synchronizedList (java.util.List)
No entanto, para limpar a lista, basta ligar para List.clear () .
Sim, é o caminho correto, mas o bloco sincronizado é necessário se você quer todas as remoções em conjunto para ser seguro - a menos que a fila está vazia há remoções permitidos. Meu palpite é que você só quer fila de seguro e operações dequeue, para que possa remover o bloco sincronizado.
No entanto, há filas simultâneos muito avançadas em Java, como ConcurrentLinkedQueue
Vamos dar uma lista normal (implementada pela classe ArrayList) e torná-lo sincronizado. Isto é mostrado na classe SynchronizedListExample. Passamos o método Collections.synchronizedList um novo ArrayList de strings. O método retorna uma lista sincronizada de Strings. // Aqui é a classe 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());
}
}
}
}
Observe que quando a iteração sobre a lista, este acesso ainda é feito usando um bloco sincronizado que os bloqueios no objeto synchronizedList. Em geral, a iteração sobre uma coleção sincronizado deve ser feito em um bloco sincronizado