자바로 작업을 하던 중 다음과 같은 에러를 만났다.
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