java.util.ConcurrentModificationException - Android

标签 java android

我有时会从下面的代码中得到以下异常 人们建议如果我对迭代器进行 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/

相关文章:

android - findFirstAsync() 返回 "invalid object"但 findFirst() 或 findAllAsync() 有效

java - 订阅数据馈送的多个并发用户的设计和架构

java - 并行无限 Java 流耗尽内存

java - Solr CloudSolrClient : Caused by: java. lang.ClassCastException : java. lang.String 无法转换为 java.util.Map

android - 如何在后台完成任务后显示弹出窗口?

android - FontRenderer 缓存已满

java - 如何在 Java 中逐个元素地比较两个数组?

java - 使用此自定义格式解析 DateTime

java - 使用 php 和 android 从 sql 数据库中选择所有内容

Android 跨页面传播 TableLayout