Middle
O que pode contar sobre coleções multithread em Java?
sobes.tech IA
Resposta da IA
As coleções concorrentes em Java fornecem formas seguras de trabalhar com dados de múltiplos threads simultaneamente, prevenindo condições de corrida e outros problemas de sincronização.
As principais interfaces e classes incluem:
ConcurrentMap: EstendeMap, garantindo operações atômicas.ConcurrentHashMap: Implementação de alto desempenho que não bloqueia toda a mapa durante modificações. Garante segurança em múltiplos threads sem bloqueio completo.
CopyOnWriteArrayListeCopyOnWriteArraySet: Coleções seguras para threads que criam uma cópia do array base em cada modificação. São adequadas para coleções que são lidas frequentemente e modificadas raramente. A leitura ocorre sem bloqueio.BlockingQueue: Interface de fila que suporta operações de espera até que a fila esteja vazia ou cheia. Usada para organizar a interação entre threads, por exemplo, no padrão produtor-consumidor.ArrayBlockingQueue: Implementação deBlockingQueuebaseada em array com capacidade fixa.LinkedBlockingQueue: Implementação deBlockingQueuebaseada em lista ligada com capacidade opcional.SynchronousQueue: Fila com capacidade zero. Cada operação de inserção espera por uma operação de extração correspondente e vice-versa.
ConcurrentLinkedQueue: Implementação segura para threads deQueuebaseada em lista ligada. Não suporta operações de bloqueio.
Diferenças com coleções sincronizadas (Collections.synchronizedList, Collections.synchronizedMap, etc.):
- Coleções sincronizadas usam bloqueio completo ao nível do objeto, o que pode reduzir o desempenho em alta concorrência.
- Coleções concorrentes, como
ConcurrentHashMap, usam bloqueio mais granular ou outros mecanismos para alcançar melhor desempenho. - Os iteradores de coleções sincronizadas podem lançar
ConcurrentModificationExceptionse a coleção for modificada durante a iteração de outro thread. Os iteradores de coleções concorrentes geralmente são mais resistentes a essas mudanças.
A escolha de uma coleção concorrente específica depende do cenário de uso: frequência de leitura/escrita, necessidade de operações de bloqueio, requisitos de desempenho, etc.
Exemplo de uso de ConcurrentHashMap:
import java.util.concurrent.ConcurrentHashMap;
public class ConcurrentExample {
private final ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();
public void updateValue(String key, Integer value) {
map.put(key, value); // Operação segura para threads
}
public Integer getValue(String key) {
return map.get(key); // Operação segura para threads
}
public void incrementValue(String key) {
// Operação atômica: se a chave não existir, insere 1, caso contrário, incrementa o valor existente
map.compute(key, (k, v) -> (v == null) ? 1 : v + 1);
}
}
Exemplo de uso de BlockingQueue:
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue;
public class ProducerConsumer {
private final BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
// Produtor
public void produce(Integer item) throws InterruptedException {
queue.put(item); // Bloqueia se a fila estiver cheia
System.out.println("Produced: " + item);
}
// Consumidor
public Integer consume() throws InterruptedException {
Integer item = queue.take(); // Bloqueia se a fila estiver vazia
System.out.println("Consumed: " + item);
return item;
}
}