Dlaczego czasami otrzymujemy ConcurrentModificationException podczas iteracji w Java?

ConcurrentModificationException w Java jest wyjątkiem, który może pojawić się podczas modyfikacji kolekcji, gdy jednocześnie trwa przez nią iteracja. Jest to typowy błąd, który występuje w wielowątkowych aplikacjach, ale może się zdarzyć także w pojedynczym wątku, gdy kolekcja jest modyfikowana podczas iteracji. Zrozumienie tego błędu oraz sposobów jego unikania jest kluczowe dla bezpiecznego i efektywnego zarządzania kolekcjami w Java.

Przykład kodu

Załóżmy, że mamy listę, po której iterujemy, jednocześnie próbując usunąć z niej elementy. Oto przykład, jak to zazwyczaj się robi i dlaczego prowadzi to do błędu:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ConcurrentModificationExample {
    public static void main(String[] args) {
        List<String> fruits = new ArrayList<>();
        fruits.add("Apple");
        fruits.add("Banana");
        fruits.add("Cherry");

        // Iterator do przeglądania listy
        Iterator<String> iterator = fruits.iterator();
        
        while (iterator.hasNext()) {
            String fruit = iterator.next();
            // Sprawdzamy, czy owoc to "Banana"
            if (fruit.equals("Banana")) {
                // Próba usunięcia elementu podczas iteracji
                fruits.remove(fruit); // Tutaj pojawi się ConcurrentModificationException
            }
        }
    }
}

W powyższym kodzie, podczas gdy iterujemy po liście fruits za pomocą iteratora, próbujemy usunąć element “Banana” bezpośrednio z listy. Modyfikacja listy w trakcie iteracji prowadzi do wygenerowania ConcurrentModificationException, ponieważ struktura listy została zmieniona, a iterator o tym nie wie.

Lepsze podejście do usuwania elementów

Aby uniknąć tego błędu, powinniśmy korzystać z metody remove dostarczanej przez iterator, która jest bezpieczna do używania podczas iteracji:

while (iterator.hasNext()) {
    String fruit = iterator.next();
    if (fruit.equals("Banana")) {
        // Bezpieczne usunięcie elementu za pomocą iteratora
        iterator.remove(); // Teraz nie pojawi się wyjątek
    }
}

Podsumowanie

ConcurrentModificationException jest wynikiem modyfikacji kolekcji podczas iteracji bez odpowiedniego uwzględnienia mechanizmów synchronizacji. Najprostszym sposobem uniknięcia tego błędu jest użycie metody remove iteratora, która jest synchronizowana z bieżącym stanem kolekcji i zapewnia, że struktura kolekcji nie zostanie naruszona podczas iteracji. Pamiętanie o tej zasadzie i stosowanie jej w praktyce jest kluczowe dla pisania bezpiecznego i stabilnego kodu w języku Java.

Jeżeli chcesz przyśpieszyć swoją naukę tworzenia stron chciałbym polecić mój kurs video Java w którym nauczysz się tego języka od podstaw do zaawansowanych jego aspektów.

Scroll to Top