<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      一次 java.util.ConcurrentModificationException 問題的fix

      其他寫的比較好的文章:http://www.rzrgm.cn/snowater/p/8024776.html

      我在一次多線程讀寫map的時候,然后再遍歷的時候也遇到了該問題。

      現場代碼

      private ConcurrentHashMap<Long, Set<Long>> m = new ConcurrentHashMap<>();
      
      // 多線程運行中
      public void test(Long p, Long value) {
          Set<Long> s = new HashSet<>();
          if (m.contains(p)) {
              s = m.get(p);
              s.add(value);
          } else {
              s.add(value);
          }
          m.put(p, s);
          for (Long id: s) {
              logger.info("" + id);
          }
      }
      

      可以看到,我是在多線程的讀寫一個線程安全的Map,但我用一個Set去讀的map,這個Set可不是線程安全的,再之后的遍歷Set的時候,就報了 java.util.ConcurrentModificationException 的錯。

      分析

      我們先看看這個錯誤是什么,下面是源碼

       /**
       * The number of times this HashMap has been structurally modified
       * Structural modifications are those that change the number of mappings in
       * the HashMap or otherwise modify its internal structure (e.g.,
       * rehash).  This field is used to make iterators on Collection-views of
       * the HashMap fail-fast.  (See ConcurrentModificationException).
       */
      transient int modCount;
      
      final class KeySet extends AbstractSet<K> {
          public final int size()                 { return size; }
          public final void clear()               { HashMap.this.clear(); }
          public final Iterator<K> iterator()     { return new KeyIterator(); }
          public final boolean contains(Object o) { return containsKey(o); }
          public final boolean remove(Object key) {
              return removeNode(hash(key), key, null, false, true) != null;
          }
          public final Spliterator<K> spliterator() {
              return new KeySpliterator<>(HashMap.this, 0, -1, 0, 0);
          }
          public final void forEach(Consumer<? super K> action) {
              Node<K,V>[] tab;
              if (action == null)
                  throw new NullPointerException();
              if (size > 0 && (tab = table) != null) {
                  int mc = modCount;
                  for (int i = 0; i < tab.length; ++i) {
                      for (Node<K,V> e = tab[i]; e != null; e = e.next)
                          action.accept(e.key);
                  }
                  if (modCount != mc)
                      throw new ConcurrentModificationException();
              }
          }
      }
      

      這個是源代碼,我們可以看到里面有個modCount來表示修改次數,每次對HashMap的操作都會增加modCount,如果在遍歷的時候,發現當前的modCount和遍歷的modCount不一致的時候,就會報錯。

      在我遇到的場景,Set的底層實際上就是用的Map的Key來做實現的,我的Set并不是一個線程安全的,而且還是一個淺拷貝(指向同一個地址),所以在多線程遍歷Set的時候,會出現modCount不一致的問題,導致報錯。

      解決辦法

      因為避免不了淺拷貝,所以我的解決辦法是將set替換成線程安全的,例如 ConcurrentHashMap,也可以是線程安全的Collection。

      其他情況的解決辦法

      將報錯的容器替換成線程安全的,例如萬能的 ConcurrentHashMap;關注任何map的修改操作,可以試著將修改操作加鎖。

      posted @ 2020-11-26 20:44  qscqesze  閱讀(226)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 人人妻人人做人人爽夜欢视频| 亚洲人成网站18禁止无码 | 亚洲丰满熟女一区二区蜜桃 | 东京热一区二区三区在线| 国产成人av免费网址| 亚洲的天堂在线中文字幕| 国产av不卡一区二区| 日本新janpanese乱熟| 亚洲中文无码手机永久| 伊人蕉久影院| 夜夜躁狠狠躁日日躁| 国产第一页浮力影院入口| 日本久久一区二区三区高清| 国产最大成人亚洲精品| 日韩无专区精品中文字幕| 91高清免费国产自产拍| 男女性高爱潮免费网站| 精品久久久久久亚洲综合网| 久草热在线视频免费播放| 国产精品一二三区久久狼| 国产精品麻豆成人av网| 日韩高清不卡免费一区二区| 欧洲亚洲成av人片天堂网| 日韩淫片毛片视频免费看| 中文字幕人妻色偷偷久久| 卢氏县| 无码专区人妻系列日韩精品少妇| 国产成人欧美日本在线观看| 99热精品毛片全部国产无缓冲 | 亚洲一区二区三区在线观看精品中文| 日本久久久久亚洲中字幕| 欧美嫩交一区二区三区| 黔西| 开心久久综合激情五月天| 欧美中文字幕无线码视频| 亚洲精品国产免费av| 国产麻传媒精品国产av| 苍井空毛片精品久久久| 日本内射精品一区二区视频| 日本五十路熟女一区二区| 国产丝袜视频一区二区三区 |