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
}
});
正如你可以看到我訪問的HashMap的塊。 ApiManager
類是一個單例。如果我在迭代它的同時鎖定對象,爲什麼會得到ConcurrentModificationException
?其他線程如何獲得鎖定?我錯過了什麼嗎?
注意:在這個例子中有3個線程。 UI線程(我稱之爲getProfile()
方法),第二個線程是套接字的內部線程(傳遞響應),另一個線程調用onSocketDisconnected()
方法。
訪問數據後,在while(iterator.hasNext())塊中調用iterator.remove。 –
https://examples.javacodegeeks.com/java-basics/exceptions/java-util-concurrentmodificationexception-how-to-handle-concurrent-modification-exception/ – Stallion