我已经阅读了很多有关此问题的SO问题,但我无法理解为什么我有java.util.ConcurrentModificationException
在课堂上我有这个:
private Set<RequestOrders> mRequests = new HashSet<>();
private final Object lock = new Object();
mRequest
对象上的所有操作都被这样的同步语句包围:
public void handleOrder(RequestOrders order) {
synchronized (lock) {
if (!mRequests.contains(order)) {
final sOrder = saveOrderOnDB(order);
mRequests.add(sOrder);
handleOrder(sOrder;
}
}
}
我收到了错误:
void notifyOrder(int type) {
if (!mPause) {
synchronized (lock) {
for (RequestOrders request : mRequests) { // Error here while iterating
if (.....) {
redirectOrders(request);
} else if (....) {
......
startService(.....);
}
}
}
} else {
.....
}
}
知道为什么吗?同步语句是否应该防止并发问题?
答案 0 :(得分:1)
在您仍然在迭代mRequest集时,可能正在发生从Set中添加/删除RequestOrders的方法调用。因此,当您仍在迭代时,mRequest集的大小正在发生变化,从而导致错误。为了克服这个问题,你可以:
1 - 创建一个临时集,其中包含要添加到mRequest的所有对象。完成对mRequest集中所有对象的循环后,将临时集中的所有对象添加到mRequest集。
2-使用并发HashMap。
以下是如何使用第一种方法的示例:
private Set<RequestOrders> mRequests = new HashSet<>();
private Set<RequestOrders> backlog = new HashSet<>();
public void handleOrder(RequestOrders order) {
synchronized (lock) {
if (!mRequests.contains(order)) {
final sOrder = saveOrderOnDB(order);
backlog.add(sOrder);
handleOrder(sOrder);
}
}
}
void notifyOrder(int type) {
if (!mPause) {
for (RequestOrders request : mRequests) { // Error here while iterating
if (.....) {
redirectOrders(request);
} else if (....) {
......
startService(.....);
}
}
mRequests.addAll(backlog);
backlog.clear();
} else {
.....
}
}