【发布时间】: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() 方法的线程。
【问题讨论】:
-
在访问数据后,在你的 while (iterator.hasNext()) 块中调用 iterator.remove。
标签: android websocket hashmap concurrentmodification