我有时会从下面的代码中得到以下异常 人们建议如果我对迭代器进行 for 循环,它会解决问题。但是我不明白如果我没有删除 for 循环中的任何元素而是调用 pendingActions.clear();之后。 如果有人遇到过任何这种情况,请告诉我。 另外,如果我对
进行列表声明,您会认为private List<Action> pendingActions = Collections.synchronizedList(new ArrayList<>());
会解决这个问题吗?
private List<Action> pendingActions = new ArrayList<>();
private void runPendingNavigationActions() {
if (!pendingActions.isEmpty()) {
for (Action r : pendingActions) {
r.run();
}
pendingActions.clear();
}
}
异常:
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4156)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4250)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1839)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:158)
at android.app.ActivityThread.main(ActivityThread.java:7229)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)
Caused by: java.util.ConcurrentModificationException
at java.util.ArrayList$ArrayListIterator.next(ArrayList.java:573)
at com.app.android.view.fragment.MainFragment.runPendingNavigationActions(MainFragment.java:1355)
最佳答案
您使用了错误的数据结构:Queue
是更好的选择,特别是为并发修改而设计的。
例如,您可以使用 LinkedBlockingQueue
.您可以将其添加到列表中,然后使用添加的操作,例如:
Action r;
while ((r = queue.poll()) != null) {
r.run();
}
使用 Collections.synchronizedList
不会解决您的问题,至少不能解决问题本身。
使用 Collections.synchronizedList()
包装列表时要记住的是,它只为每个单独的方法调用 提供互斥,例如直到调用 pendingActions.get()
或 pendingActions.iterator()
返回。
增强的for循环隐式创建了一个Iterator
;但是当你遍历它时,列表并没有被锁定,无论它是否来自同步列表。
您的其他线程在此迭代期间正在更改列表,并且在您下次尝试从迭代器获取值时仍会导致 ConcurrentModificationException
。
现在,您可以通过将迭代包装在 synchronized
block 以及中使其工作(没有 CME):
synchronized (pendingActions) {
for (Action r : pendingActions) {
r.run();
}
r.clear();
}
问题是在迭代列表时其他线程现在将被阻塞。这可能会导致您的应用出现明显的延迟;也可能不会,具体取决于调用此方法的频率以及操作运行所需的时间。
但是,使用并发队列完全避免了这个问题,并且可能比同步列表更快,因为非阻塞并发队列不需要使用“完全”同步。
关于java.util.ConcurrentModificationException - Android,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37851660/