logo

ConcurrentModificationException em Java

A ConcurrentModificationException ocorre quando um objeto tenta ser modificado simultaneamente quando não é permitido. Esta exceção geralmente surge quando se está trabalhando com Classes de coleção Java .

Por exemplo - Não é permitido que um thread modifique uma coleção quando algum outro thread está iterando sobre ela. Isso ocorre porque o resultado da iteração torna-se indefinido com ela. Algumas implementações da classe Iterator lançam esta exceção, incluindo todas as implementações de propósito geral do Iterator que são fornecidas pelo JRE. Iteradores que fazem isso são chamados falha rápida já que eles lançam a exceção rapidamente assim que encontram tal situação, em vez de enfrentar um comportamento indeterminado da coleção em qualquer momento no futuro.

código fibonacci java

Observação:Não é obrigatório que esta exceção seja lançada somente quando algum outro thread tentar modificar um objeto Collection. Também pode acontecer se um único thread tiver alguns métodos chamados que estão tentando violar o contrato do objeto. Isso pode acontecer quando um thread está tentando modificar o objeto Collection enquanto ele está sendo iterado por algumiterador fail-fast, o iterador lançará a exceção.

Exemplo

 import java.awt.List; import java.util.*; public class Concurrentmodificationexception { public static void main(String[] args) { ArrayList list = new ArrayList(); list.add(1); list.add(2); list.add(3); list.add(4); list.add(5); Iterator it = list.iterator(); while (it.hasNext()) { Integer value = it.next(); System.out.println('List Value:' + value); if (value.equals(3)) list.remove(value); } } } 

Saída:

ConcurrentModificationException em Java

Esta mensagem diz que a exceção é lançada quando o próximo método é chamado, pois o iterador está iterando a lista e estamos fazendo modificações nela simultaneamente. Mas se fizermos modificações no hashmap como mostrado abaixo, então não haverá nenhuma exceção, pois o tamanho do hashmap não mudará.

Por exemplo-

 import java.awt.List; import java.util.*; public class concurrentmodificationexception { public static void main(String[] args) { HashMap map = new HashMap(); map.put(1, 1); map.put(2, 2); map.put(3,3); Iterator it = map.keySet().iterator(); while(it.hasNext()) { Integer key = it.next(); System.out.println('Map Value:' + map.get(key)); if (key.equals(2)) { map.put(1, 4); } } } } 

Saída:

código abs c
 Map Value:1 Map Value:2 Map Value:3 

Este exemplo funciona perfeitamente bem, pois enquanto o iterador está iterando no mapa, o tamanho do mapa não muda. Apenas o mapa está sendo atualizado no declaração if .

Construtores de ConcurrentModificationException

Existem 4 tipos de construtores de ConcurrentModificationException -

classe abstrata em java
  1. public ConcurrentModificationException() -
    Isso cria uma ConcurrentModificationException sem parâmetros.
  2. public ConcurrentModificationException (mensagem de string)
    Isso cria uma ConcurrentModificationException com uma mensagem detalhada especificando a Exceção.
  3. public ConcurrentModificationException (causa lançável)
    Isso cria uma ConcurrentModificationException com uma causa e uma mensagem que é (cause==null?null:cause.toString()). A causa é recuperada posteriormente pelo Throwable.getCause().
  4. public ConcurrentModificationException (mensagem de string, causa que pode ser lançada)
    Isso cria uma ConcurrentModificationException com uma mensagem detalhada e uma causa. (causa==nulo?nulo:causa.toString()). A mensagem é recuperada posteriormente por Throwable.getMessage() e a causa é recuperada posteriormente por Throwable.getCause().

Como evitar ConcurrentModificationException em um ambiente multithread?

Para evitar o ConcurrentModificationException em um ambiente multithread, podemos seguir as seguintes maneiras-

  1. Em vez de iterar na classe de coleção, podemos iterar no array. Desta forma, podemos trabalhar muito bem com listas de tamanho pequeno, mas isso irá esgotar o desempenho se o tamanho do array for muito grande.
  2. Outra forma pode ser bloquear a lista colocando-a no bloco sincronizado. Esta não é uma abordagem eficaz, pois o único propósito de usar multi-threading é abandonado por isso.
  3. JDK 1.5 ou superior fornece classes ConcurrentHashMap e CopyOnWriteArrayList. Essas classes nos ajudam a evitar exceções de modificação simultânea.

Como evitar ConcurrentModificationException em um ambiente de thread único?

Usando a função remove() do iterador, você pode remover um objeto de um objeto de coleção subjacente.