본문 바로가기

Trouble Shootings

자바: java.util.ConcurrentModificationException 에러

자바로 작업을 하던 중 다음과 같은 에러를 만났다.

 

Exception in thread "main" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
	at java.util.ArrayList$Itr.next(ArrayList.java:859)
...

 

구글 검색을 해보니 List와 같은 객체를 for each 문을 돌릴 때, 해당 객체를 수정하면 발생한다고 한다. 그리고 보통 해당상황이 발생하는 경우는 크게 두가지 경우가 있다고 한다.

 

  • 싱글 스레드 환경에서 for each문 중간에 객체를 수정하는 경우
  • 멀티 스레드 환경에서, 다른 스레드에서 객체 값이 수정된 경우.

어떠한 경우든 for each 중에 해당 객체를 수정한다는 사실은 동일하다. 결론적으로 이를 해결하기 위해서는 

 

  • for each 중에는 객체를 수정하지 않는다. 만약 수정해야 한다면 바로 break로 반복문을 빠져 나온다.
AS IS -----------------------------------------------

List<Integer> localList = new ArrayList<Integer>();
    	
for(Integer obj : localList) {
	if(obj.equals(10)) {
		localList.remove(obj);
	}
}


TO BE -----------------------------------------------

List<Integer> localList = new ArrayList<Integer>();
    	
for(Integer obj : localList) {
	if(obj.equals(10)) {
		localList.remove(obj);
		break;
	}
}

 

  • 멀티 스레드 환경에서는, 객체 수정이 없는 단순 for each 문을 도는 중에도 에러가 발생할 수 있다. 다른 스레드에서 해당 객체를 수정할 수 있기 때문이다. 이럴때는 성능을 조금 손해보더라도 for each 문을 단순 for 문으로 바꾸는 것도 방법중 하나이다.
AS IS ------------------------------------

// 단순 출력중에도, 다른 스레드에서 myList를 수정하면 에러가 발생한다.
for(Integer obj : myList) {
	System.out.println(obj);
}


BO BE ------------------------------------

for(int i = 0; i < myList.size(); i++) {
	System.out.println(myList.get(i));
}

 

728x90