본문 바로가기

Programming/Java

ConcurrentModificationException

728x90

Java에서 ConcurrentModificationException은 컬렉션을 동시에 수정하려고 할 때 발생합니다. 이 예외는 다른 스레드나 iterator가 컬렉션을 수정하는 동안, 현재 스레드에서 해당 컬렉션을 수정하려고 할 때 발생합니다.

 

예를 들어, 다음과 같은 코드에서는 ConcurrentModificationException이 발생할 수 있습니다.

List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
for (Integer number : numbers) {
    if (number == 3) {
        numbers.remove(number);
    }
}

 코드에서는 numbers 리스트에서 iterator 통해 요소를 순회하면서, 요소가 3 경우 해당 요소를 삭제하려고 합니다. 그러나, ArrayList 내부적으로 배열을 사용하고, 요소를 삭제하면 배열의 크기가 변경될  있습니다. 이때, 다른 스레드나 iterator 컬렉션을 동시에 수정하려고 하면 ConcurrentModificationException발생할  있습니다.

 

 

해결 방법은 다음과 같습니다.

 

1. iterator를 사용하여 컬렉션을 수정하기 컬렉션을 수정할 때는 iterator를 사용하여 컬렉션을 수정해야 합니다. iterator는 내부적으로 컬렉션을 변경하는 것을 방지하기 때문에, 이 방법으로는 ConcurrentModificationException을 피할 수 있습니다.

List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
Iterator<Integer> iterator = numbers.iterator();
while (iterator.hasNext()) {
    Integer number = iterator.next();
    if (number == 3) {
        iterator.remove();
    }
}

 

2. 동기화된 컬렉션 사용하기 Java는 동기화된 컬렉션을 제공합니다. 이 컬렉션은 여러 스레드에서 동시에 접근할 수 있도록 설계되어 있으므로, 여러 스레드에서 컬렉션을 수정할 때 ConcurrentModificationException을 방지할 수 있습니다.

List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
List<Integer> synchronizedNumbers = Collections.synchronizedList(numbers);

 

3. 스트림을 사용하여 컬렉션을 수정하기 Java 8부터는 스트림을 사용하여 컬렉션을 수정할 수 있습니다. 이 경우, ConcurrentModificationException을 방지할 수 있습니다.

List<Integer> numbers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
numbers.removeIf(number -> number == 3);

 코드에서는 removeIf 메소드를 사용하여 컬렉션을 수정합니다.  메소드는 요소를 삭제하기 위해 내부적으로 iterator를 사용합니다.

728x90