【问题标题】:HashMap iterator ConcurrentModificationExceptionHashMap 迭代器 ConcurrentModificationException
【发布时间】:2017-05-30 10:36:39
【问题描述】:

我收到了ConcurrentModificationException,但我不知道如何解决。

我有一个 Android 多线程应用程序(与套接字通信),我正在将回调(接口)存储到哈希图中。

public class ApiManager {

   private static ApiManager instance;

   public synchronized ApiManager getInstance() {
      if (instance == null)
         instance = new ApiManager();

      return instance;  
   }

   private final HashMap<String, Callback> callbacks = new HashMap<>;

   // Setters and getters for storing callbacks

   private @Nullable Callback getCallback(@NoNull String key) {
      synchronized (callbacks) {
         return callbacks.get(key);
      }
   }

   private void addCallback(@NonNull String key, @NonNull Callback callback) {
      synchronized (callbacks) {
         callbacks.put(key, callback); 
      }
   }

   private void removeCallback(@NonNull String key) {
       synchronized (callbacks) {
          callbacks.remove(key);
       }
   }

   // Request to retrieve the user's profile from server
   public synchronized void getProfile(String key, Callback callback) {
      // Save the callback
      addCallback(key, callback);

      // Do the asynchronous request
      getSocket().emit("getProfile", new Ack() {
         @Override
         public void call(Object... args) {
            // Deliver the response
            Callback callback = getCallback(key);
            if (callback != null)
               callback.onResponse(args);  

            // Remove the callback
            removeCallback(key);                
         }
      });
   }

   // Called when the socket disconnects
   // ----> This is the method where I get the exception !
   private void onSocketDisconnect() {

      /*
       * Notify stored callbacks that the socket has disconnected
       */ 

      synchronized (callbacks) {
         Set<Map.Entry<String, Callback>> set = callbacks.entrySet();
         if (set.size() > 0) {
            Iterator<Map.Entry<String, Callback>> iterator = set.iterator();
            while (iterator.hasNext()) {
               // This is the line where the exception occurres
               Map.Entry<String, Callback> entry = iterator.next();

               String key = entry.getKey();
               Callback callback = entry.getValue();

               if (callback != null) {
                  // Notify callback that there was a socket disconnect exception
                 callback.onResponse(Factory.buildResponseFailure(SOCKET_DISC));

                  it.remove();
               }
            }
         }
      }
   }
}

而且有时会出现异常:

Exception: java.util.ConcurrentModificationException
at java.util.HashMap$HashIterator.nextEntry(HashMap.java:851)
       at java.util.HashMap$EntryIterator.next(HashMap.java:891)
       at java.util.HashMap$EntryIterator.next(HashMap.java:890)

这就是我检索用户个人资料的方式:

ApiManager.getInstance().getProfile(KEY_PROFILE_REQ, new Callback() {
   @Override
   public void onResponse(Object... args) {
      // Parsing the data 
   }
});

如您所见,我正在访问 synchronized 块中的哈希图。 ApiManager 类是单例。如果我在迭代对象时锁定对象,为什么会得到ConcurrentModificationException?其他线程如何获得锁?我错过了什么吗?

注意:在这个例子中是 3 个线程。 UI 线程(这里我调用getProfile() 方法),第二个线程是套接字的内部线程(传递响应)和另一个调用onSocketDisconnected() 方法的线程。

【问题讨论】:

标签: android websocket hashmap concurrentmodification


【解决方案1】:

在对集合进行迭代时从集合中删除一个项目可能会导致这种情况。您是否尝试过将要删除的项目存储在某处,然后在处理完最终元素后 set.removeAll(somewhere)?

【讨论】:

    猜你喜欢
    • 2013-08-29
    • 1970-01-01
    • 2017-11-11
    • 1970-01-01
    • 2013-09-26
    • 2017-10-18
    • 1970-01-01
    • 2015-12-23
    • 1970-01-01
    相关资源
    最近更新 更多