私は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()
メソッドを呼び出す別のスレッドです。
while(iterator.hasNext())ブロックでは、データにアクセスした後にiterator.removeを呼び出してブロックします。 –
https://examples.javacodegeeks.com/java-basics/exceptions/java-util-concurrentmodificationexception-how-to-handle-concurrent-modification-exception/ – Stallion