본문 바로가기

나의 플랫폼/안드로이드

[ Android ] java.util.concurrentmodificationexception

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

 먼저, 지금 제가 적는 내용은 경험을 토대로 한 내용이므로, 이론적으로 말씀 드리기엔 실력이 부족하다는 점을
염두에 두시면 감사하겠습니다. 먼가 잘못된 점이 있다고 생각하시는 분은 주저말고 댓글 달아주시면 성심 성의 껏
고치도록 하겠습니다.



 위 Exception은 List나 Map 류등을 사용할 때 발생한다.
저는 대부분 리스트나 Map을 사용할 때 당연 , index 변수를 만들어서 반복문을 돌리거나,
새로운 for문을 이용하여 편안하게 돌리기도 한다.

문제는, index변수를 사용했을 경우!

상황 ) Main Thread를 돌리는 상태에서 별개의 AsyncTask를 돌렸다.
AsyncTask에서 만들어진 클래스를 MainThread에서 List나 Map에 저장을 시킨다.


private Map<Integer,Class> mapList = new HashMap<Integer,Class>();

for(int index = 0 ; index <  mapList.size() ; index++)

{

           final  Class class =   mapList.get(index);
           ..... 

         mapList .remove(index);
}


위와 같을 경우, mapList가 AsyncTask의 의해 추가된 mapList와 엉키게 되어 다른 memory로 연결되어 버리거나 지워져버리는 오류를
범할 수 있게 된다.
멀티 쓰레드를 사용할 때 정말 위험한 부분인 것 같다.


그래서 다음과 같이 수정을 해보았다.

private Map<Integer,Class> mapList = new HashMap<Integer,Class>(); 

synchronized ( mapList  ){

      Iterator< Integer > it = this.mapList.keySet().iterator();

        while(it.hasNext()){

        Integer index = it.next();

        final Class class = this. mapList .get(index);

        if( class != null){
    ....
                   it.remove(); 

}
       } 



Iterator를 이용하여 HashMap을 가져온 후, 변하지 않는 선에서 처리를 하도록 하였다.
절대 외부의 변경사항은 이 부분에서 적용이 되지 않게 처리 한 것이다.

삭제하는 위치도 Map의 직접적으로 처리하지 않고 Iterator를 이용해보니,
버그도 나지 않고, 위와 같은 Exception도 사라졌다.


!!!!!!!참고

ArrayList 나 Hashmap을 사용할 때 위와 같은  Exception이 발생할 가능성이 있을 경우

JDK1.5 이상에서는  ConcurrentHashMap과 CopyOnWriteArrayList 클래스 를 사용하시는 것을 권장합니다.

위 Iterator는 멀티스레드의 혜택을 막아버리기 때문에 권장하지 않는다는 군요. 참고하세요^^


출처:  http://www.javacodegeeks.com/2011/05/avoid-concurrentmodificationexception.html 
그리고 혹시나 remove를 할 경우에는 

synchronized (this.threadList){

       for( Iterator< String > it = this.threadList.iterator(); it.hasNext() ; )

       {

        try{

        String value = it.next();

    if(// 먼가 조건문){

    this.threadList.remove(it);

    }

        }catch (java.util.ConcurrentModificationException e) {

        Log.e(Const.DEBUG_TAG , "Update random pattern thread. ",e);

}

       }

        }


 위와 같이 해주세요. 그렇지 않을 경우 또!
UnsupportedOperationException 

이 발생합니다. ^^

그럼 오늘도 즐코딩