關(guān)于HashMap的Concurrentmodificationexception

錯(cuò)誤堆棧如下

java.util.ConcurrentModificationException
        at java.util.HashMap$HashIterator.nextEntry(HashMap.java:922)
        at java.util.HashMap$KeyIterator.next(HashMap.java:956)
        ...

hashMap的相關(guān)實(shí)現(xiàn)源碼如下:

final Entry<K,V> nextEntry() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            Entry<K,V> e = next;
            if (e == null)
                throw new NoSuchElementException();

            if ((next = e.next) == null) {
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)
                    ;
            }
            current = e;
            return e;
        }

        public void remove() {
            if (current == null)
                throw new IllegalStateException();
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            Object k = current.key;
            current = null;
            HashMap.this.removeEntryForKey(k);
            expectedModCount = modCount;
        }

顯然,工程中使用了迭代器遍歷hashMap時(shí)并且map的size被修改過(guò)了,導(dǎo)致modCount != expectedModCount,原因是hash迭代器在將modCount賦值給expectedModCount后,modCount的值被其它線程修改掉了。

  private abstract class HashIterator<E> implements Iterator<E> {
        Entry<K,V> next;        // next entry to return
        int expectedModCount;   // For fast-fail
        int index;              // current slot
        Entry<K,V> current;     // current entry

        HashIterator() {
            expectedModCount = modCount;
            if (size > 0) { // advance to first entry
                Entry[] t = table;
                while (index < t.length && (next = t[index++]) == null)
                    ;
            }
        }

解決方法:使用ImmutableMap進(jìn)行線程安全的復(fù)制。

 hashMap = ...
 copyUserMap = ImmutableMap.copyOf(hashMap);
 Iterator<String> keys = copyUserMap.keySet().iterator();
 while (keys.hasNext()) {
               ...
 }

由于HashMap是線程不安全的,這樣在遍歷的時(shí)候不會(huì)因?yàn)槎嗑€程的修改map而導(dǎo)致并發(fā)異常。除了該方法,還可以使用concurrentHashMap,獲取線程鎖解決。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容