Coleção CopyOnWrite
Exploramos muitas coleções sincronizadas juntos e, se você dominou as outras, esta será ainda mais simples.
Exemplo do Mundo Real
Uma aplicação web que utiliza CopyOnWriteArrayList para armazenar assinantes de eventos. Várias threads podem recuperar simultaneamente uma lista dos assinantes atuais para notificá-los sobre alterações, enquanto outras threads podem adicionar ou remover assinantes.
Diferenças em Relação a Outros Tipos
Coleções CopyOnWrite criam uma cópia da coleção toda vez que uma alteração é feita, garantindo que as operações de leitura não sejam bloqueadas por mudanças nos dados, proporcionando assim segurança de thread para leituras, embora as operações de escrita não sejam thread-safe, pois ocorrem em uma cópia separada da coleção.
Visões CopyOnWrite:
Como podemos ver na imagem, ao adicionar um novo item, é feita uma cópia dessa estrutura de dados; todas as threads que estavam trabalhando com essa coleção antes da alteração continuarão seu trabalho sem problemas, pois essas mudanças não afetarão a cópia CopyOnWrite que elas utilizam!
CopyOnWriteArraySet
CopyOnWriteArraySet é uma implementação thread-safe de um conjunto baseada em CopyOnWriteArrayList. Garante a segurança de threads criando uma nova cópia do conjunto base toda vez que ocorre uma alteração, como adição ou remoção de elementos.
Essa abordagem é especialmente útil quando o conjunto é lido frequentemente e modificado raramente, pois fornece uma visão consistente do conjunto para todas as threads sem exigir sincronização.
CopyOnWriteArrayList
CopyOnWriteArrayList é uma variante thread-safe de ArrayList que garante a segurança de threads criando uma nova cópia do array subjacente toda vez que ele é modificado.
Esse design oferece um iterador tolerante a falhas que não lança ConcurrentModificationException, pois opera em um snapshot do array tirado no momento em que o iterador foi criado. É mais adequado para situações em que as operações de leitura são significativamente mais frequentes do que as operações de escrita, já que o custo de copiar todo o array a cada escrita pode ser considerável.
Exemplo Prático de Caso de Uso
Métodos da coleção CopyOnWrite
addIfAbsent(E e): Adiciona um elemento à lista apenas se ele ainda não estiver presente na lista/múltiplos.
Main.java
123456789101112131415161718192021package com.example; import java.util.concurrent.CopyOnWriteArrayList; public class Main { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); list.add("apple"); list.add("banana"); // Attempt to add a duplicate element list.addIfAbsent("apple"); // This will not add "apple" again // Adding a new element list.addIfAbsent("orange"); // This will add "orange" System.out.println(list); // Output: [apple, banana, orange] } }
Neste exemplo, "apple" não é adicionada novamente porque já existe na lista. O método addIfAbsent() impede entradas duplicadas, mantendo a unicidade dos elementos.
addAllAbsent(Collection<? extends E> c): Adiciona todos os elementos da coleção especificada à lista/coleção, ignorando elementos já existentes.
Main.java
12345678910111213141516171819202122package com.example; import java.util.Arrays; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class Main { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); list.add("apple"); list.add("banana"); List<String> newFruits = Arrays.asList("banana", "cherry", "date"); // Adding elements from the collection, ignoring duplicates list.addAllAbsent(newFruits); System.out.println(list); // Output: [apple, banana, cherry, date] } }
Neste exemplo, "banana" já está presente na lista, portanto addAllAbsent() não a adicionará novamente. O método garante que apenas elementos únicos da coleção fornecida sejam adicionados à lista.
Todos os outros métodos das coleções CopyOnWrite são semelhantes aos de suas coleções pai; eles simplesmente copiam o estado da coleção sempre que alterações são feitas.
Limitações e Vantagens
😔Limitações:
Coleções CopyOnWrite possuem limitações notáveis. Elas geram um custo de memória devido à criação de uma nova cópia da coleção toda vez que uma alteração é feita, o que pode ser substancial. Esse projeto as torna menos adequadas para cenários onde são necessárias mudanças frequentes nos dados.
💪Vantagens:
Por outro lado, coleções CopyOnWrite oferecem vantagens significativas. Elas são altamente eficientes para leitura de dados em ambientes multithread. Essas coleções apresentam desempenho excepcional em situações onde as operações de leitura superam significativamente as operações de escrita, tornando-as uma excelente escolha para esses casos de uso.
No entanto, devido à cópia a cada alteração, coleções CopyOnWrite podem consumir mais memória e não são adequadas para cenários com operações de escrita frequentes. Elas são mais eficazes quando as operações de leitura predominam sobre as de escrita.
1. O que acontece ao chamar o método addIfAbsent(E e) em CopyOnWriteArrayList?
2. Por que coleções CopyOnWrite são particularmente adequadas para cenários com leituras frequentes e poucas alterações de dados?
Obrigado pelo seu feedback!
Pergunte à IA
Pergunte à IA
Pergunte o que quiser ou experimente uma das perguntas sugeridas para iniciar nosso bate-papo
What are some common use cases for CopyOnWrite collections?
Can you explain the main differences between CopyOnWriteArrayList and CopyOnWriteArraySet?
When should I avoid using CopyOnWrite collections?
Awesome!
Completion rate improved to 3.33
Coleção CopyOnWrite
Deslize para mostrar o menu
Exploramos muitas coleções sincronizadas juntos e, se você dominou as outras, esta será ainda mais simples.
Exemplo do Mundo Real
Uma aplicação web que utiliza CopyOnWriteArrayList para armazenar assinantes de eventos. Várias threads podem recuperar simultaneamente uma lista dos assinantes atuais para notificá-los sobre alterações, enquanto outras threads podem adicionar ou remover assinantes.
Diferenças em Relação a Outros Tipos
Coleções CopyOnWrite criam uma cópia da coleção toda vez que uma alteração é feita, garantindo que as operações de leitura não sejam bloqueadas por mudanças nos dados, proporcionando assim segurança de thread para leituras, embora as operações de escrita não sejam thread-safe, pois ocorrem em uma cópia separada da coleção.
Visões CopyOnWrite:
Como podemos ver na imagem, ao adicionar um novo item, é feita uma cópia dessa estrutura de dados; todas as threads que estavam trabalhando com essa coleção antes da alteração continuarão seu trabalho sem problemas, pois essas mudanças não afetarão a cópia CopyOnWrite que elas utilizam!
CopyOnWriteArraySet
CopyOnWriteArraySet é uma implementação thread-safe de um conjunto baseada em CopyOnWriteArrayList. Garante a segurança de threads criando uma nova cópia do conjunto base toda vez que ocorre uma alteração, como adição ou remoção de elementos.
Essa abordagem é especialmente útil quando o conjunto é lido frequentemente e modificado raramente, pois fornece uma visão consistente do conjunto para todas as threads sem exigir sincronização.
CopyOnWriteArrayList
CopyOnWriteArrayList é uma variante thread-safe de ArrayList que garante a segurança de threads criando uma nova cópia do array subjacente toda vez que ele é modificado.
Esse design oferece um iterador tolerante a falhas que não lança ConcurrentModificationException, pois opera em um snapshot do array tirado no momento em que o iterador foi criado. É mais adequado para situações em que as operações de leitura são significativamente mais frequentes do que as operações de escrita, já que o custo de copiar todo o array a cada escrita pode ser considerável.
Exemplo Prático de Caso de Uso
Métodos da coleção CopyOnWrite
addIfAbsent(E e): Adiciona um elemento à lista apenas se ele ainda não estiver presente na lista/múltiplos.
Main.java
123456789101112131415161718192021package com.example; import java.util.concurrent.CopyOnWriteArrayList; public class Main { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); list.add("apple"); list.add("banana"); // Attempt to add a duplicate element list.addIfAbsent("apple"); // This will not add "apple" again // Adding a new element list.addIfAbsent("orange"); // This will add "orange" System.out.println(list); // Output: [apple, banana, orange] } }
Neste exemplo, "apple" não é adicionada novamente porque já existe na lista. O método addIfAbsent() impede entradas duplicadas, mantendo a unicidade dos elementos.
addAllAbsent(Collection<? extends E> c): Adiciona todos os elementos da coleção especificada à lista/coleção, ignorando elementos já existentes.
Main.java
12345678910111213141516171819202122package com.example; import java.util.Arrays; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; public class Main { public static void main(String[] args) { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); list.add("apple"); list.add("banana"); List<String> newFruits = Arrays.asList("banana", "cherry", "date"); // Adding elements from the collection, ignoring duplicates list.addAllAbsent(newFruits); System.out.println(list); // Output: [apple, banana, cherry, date] } }
Neste exemplo, "banana" já está presente na lista, portanto addAllAbsent() não a adicionará novamente. O método garante que apenas elementos únicos da coleção fornecida sejam adicionados à lista.
Todos os outros métodos das coleções CopyOnWrite são semelhantes aos de suas coleções pai; eles simplesmente copiam o estado da coleção sempre que alterações são feitas.
Limitações e Vantagens
😔Limitações:
Coleções CopyOnWrite possuem limitações notáveis. Elas geram um custo de memória devido à criação de uma nova cópia da coleção toda vez que uma alteração é feita, o que pode ser substancial. Esse projeto as torna menos adequadas para cenários onde são necessárias mudanças frequentes nos dados.
💪Vantagens:
Por outro lado, coleções CopyOnWrite oferecem vantagens significativas. Elas são altamente eficientes para leitura de dados em ambientes multithread. Essas coleções apresentam desempenho excepcional em situações onde as operações de leitura superam significativamente as operações de escrita, tornando-as uma excelente escolha para esses casos de uso.
No entanto, devido à cópia a cada alteração, coleções CopyOnWrite podem consumir mais memória e não são adequadas para cenários com operações de escrita frequentes. Elas são mais eficazes quando as operações de leitura predominam sobre as de escrita.
1. O que acontece ao chamar o método addIfAbsent(E e) em CopyOnWriteArrayList?
2. Por que coleções CopyOnWrite são particularmente adequadas para cenários com leituras frequentes e poucas alterações de dados?
Obrigado pelo seu feedback!