2017-05-30 24 views
1

私はConcurrentModificationExceptionを取得していますが、修正方法はわかりません。HashMap反復子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(); 
       } 
      } 
     } 
     } 
    } 
} 

そして、時には例外occurres:

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 
    } 
}); 

あなたは私が​​ブロックでハッシュマップにアクセスしています見ることができるように。 ApiManagerクラスはシングルトンです。反復中にオブジェクトをロックすると、なぜ私はConcurrentModificationExceptionを取得しますか?他のスレッドはどのようにロックを取得しますか?何か不足していますか?

注:この例では3つのスレッドがあります。 UIスレッド(私はgetProfile()メソッドを呼び出します)、2番目のスレッドはソケットの内部スレッド(配信応答)とonSocketDisconnected()メソッドを呼び出す別のスレッドです。

+0

while(iterator.hasNext())ブロックでは、データにアクセスした後にiterator.removeを呼び出してブロックします。 –

+0

https://examples.javacodegeeks.com/java-basics/exceptions/java-util-concurrentmodificationexception-how-to-handle-concurrent-modification-exception/ – Stallion

答えて

0

コレクションからアイテムを削除してコレクションから削除すると、この問題が発生する可能性があります。どこかで削除するアイテムを格納しようとしましたが、最後の要素set.removeAll(どこか)を処理した後で、

関連する問題