了解并解决 ConcurrentModificationException
Understanding and resolving ConcurrentModificationException
我正在处理一段遗留代码中间歇性的、难以重现的问题ConcurrentModificationException
:
class LegacyCode {
private final WeakHashMap<A, B> mItems = new WeakHashMap<A, B>();
public void someWork() {
final List<A> copy = new LinkedList<A>();
for (final A item : mItems.keySet()) {
copy.add(item);
}
for (final A item : copy) {
item.someMethod();
}
}
public void addItem(final A item) {
mItems.put(item, new B());
}
public void removeItem(final A item) {
mItems.remove(item);
}
}
正在投入 CME:
for (final A item : mItems.keySet()) {
copy.add(item);
}
我不完全确定我们为什么要以这种方式创建 copy
。抛出 CME 是因为在 for-each 循环为 运行 时调用了 addItem(A)
或 removeItem(A)
。
问题
我对为什么抛出 CME 的理解正确吗?
如果我将 for-each 循环替换为:
,我会避免 CME 吗?
final List<A> copy = new LinkedList<A>(mItems.keySet());
此更改是否等同于我们将要替换的 for-each 循环?据我所知,这两个片段都在 copy
.
中创建了 mItems.keySet()
的浅表副本
Is my understanding of why CME is being thrown correct?
当然可以。这正是正在发生的事情。
Will I avoid CME if I replace the for-each loop with:
final List<A> copy = new LinkedList<A>(mItems.keySet());
不,你不会,因为 LinkedList<A>
的构造函数会有类似的循环。因此,您说此更改将等同于我们将替换的 for-each 循环是正确的。
就解决这个问题而言,Java 标准库中没有现成的 WeakHashMap
class 的并发替代品。您可以通过使 addItem
和 removeItem
同步并在构造 copy
的循环周围添加同步块来解决此问题。您还可以查看解决此问题的 ,而无需在代码中使用 synchronized
。
我正在处理一段遗留代码中间歇性的、难以重现的问题ConcurrentModificationException
:
class LegacyCode {
private final WeakHashMap<A, B> mItems = new WeakHashMap<A, B>();
public void someWork() {
final List<A> copy = new LinkedList<A>();
for (final A item : mItems.keySet()) {
copy.add(item);
}
for (final A item : copy) {
item.someMethod();
}
}
public void addItem(final A item) {
mItems.put(item, new B());
}
public void removeItem(final A item) {
mItems.remove(item);
}
}
正在投入 CME:
for (final A item : mItems.keySet()) {
copy.add(item);
}
我不完全确定我们为什么要以这种方式创建 copy
。抛出 CME 是因为在 for-each 循环为 运行 时调用了 addItem(A)
或 removeItem(A)
。
问题
我对为什么抛出 CME 的理解正确吗?
如果我将 for-each 循环替换为:
,我会避免 CME 吗?final List<A> copy = new LinkedList<A>(mItems.keySet());
此更改是否等同于我们将要替换的 for-each 循环?据我所知,这两个片段都在
copy
. 中创建了
mItems.keySet()
的浅表副本
Is my understanding of why CME is being thrown correct?
当然可以。这正是正在发生的事情。
Will I avoid CME if I replace the for-each loop with:
final List<A> copy = new LinkedList<A>(mItems.keySet());
不,你不会,因为 LinkedList<A>
的构造函数会有类似的循环。因此,您说此更改将等同于我们将替换的 for-each 循环是正确的。
就解决这个问题而言,Java 标准库中没有现成的 WeakHashMap
class 的并发替代品。您可以通过使 addItem
和 removeItem
同步并在构造 copy
的循环周围添加同步块来解决此问题。您还可以查看解决此问题的 synchronized
。