[Java] HashMap 에서 ConcurrentModificationException 발생
아주 간헐적으로 발생하는 이슈가 발견됐습니다.
HashMap에서.. ConcurrentModificationException이 발생됐습니다.
java.util.ConcurrentModificationException:
at java.util.HashMap$HashIterator.nextNode (HashMap.java:1441)
at java.util.HashMap$EntryIterator.next (HashMap.java:1475)
at java.util.HashMap$EntryIterator.next (HashMap.java:1473)
at java.util.AbstractMap.toString (AbstractMap.java:554)
at java.lang.String.valueOf (String.java:2896)
at java.lang.StringBuilder.append (StringBuilder.java:132)
at com.xxx.yyy.FragmentA$4.onResponse (FragmentA.java:306)
at okhttp3.RealCall$AsyncCall.run (RealCall.kt:140)
at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)
at java.lang.Thread.run (Thread.java:764)
concurrent는 '동시에' 라는 뜻을 가지고 있습니다. 그래서 ConcurrentModificationException은.. 한글로 번역하면 동시수정에러 정도가 될 것 같네요.
ConcurrentModificationException이 발생하는 경우는 2가지가 있다고 합니다.
1. 서로 다른 Thread가 동시에 같은 HashMap에 연산을 수행 함
2. for문 안에서 HashMap의 entry를 제거함
HashMap.java코드를 봤습니다.
final Node<K,V> nextNode() {
Node<K,V>[] t;
Node<K,V> e = next;
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (e == null)
throw new NoSuchElementException();
if ((next = (current = e).next) == null && (t = table) != null) {
do {} while (index < t.length && (next = t[index++]) == null);
}
return e;
}
Exception이 발생한 위치를 보니.. modCount != expectedModCount에서 걸려서 예외가 발생했습니다.
음.. 대충보니 for문으로 HashMap을 돌고 있는데 내부 entry가 수정되서 예외가 발생한 것 같습니다.
그런데 신기한 것은.. 그냥 로그로 Log.d("TAG", "hashMap = " + hashMap); 과 같이 그냥 로그 찍는 부분에서 이 예외가 발생했네요.
hashMap.toString()에서.. 혼자 예외가 발생하진 않았을 것 같고.. 아마 다른 Thread에서 이 hashMap에 접근해서 데이터를 조작하다가.. 문제가 생긴 것 같습니다.
그래서 그냥.. HashMap을 ConcurrentHashMap으로 바꿔서 사용하려고 합니다.. ㅎㅎ
ConcurrentHashMap<String, String> myHashMap = new ConcurrentHashMap<>();
위와 같은 식으로.. 객체 타입만 HashMap이던 것을 ConcurrentHashMap으로 변경하면 됩니다.
ConcurrentHashMap은 동기화되면서 작업되므로.. 그냥 HashMap보다는 더 느리다고 하는데 뭐.. 체감이 될까 싶네요.
어쨋든 이렇게 수정하고 경과를 보겠습니다.
참고
https://www.benchresources.net/map-how-concurrentmodificationexception-can-be-handled-in-java/
댓글 영역