Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
java.util.ConcurrentModificationException-Android_Java_Android - Fatal编程技术网

java.util.ConcurrentModificationException-Android

java.util.ConcurrentModificationException-Android,java,android,Java,Android,我有时会从下面的代码中得到以下异常 人们建议,如果我将for循环设置为迭代器,它将解决这个问题。但是我不明白我是不是在删除for循环中的任何元素,而是调用pendingActions.clear;后来 如果有人遇到过这种情况,请告诉我。 另外,如果我向你做一份清单声明,你会考虑吗 private List<Action> pendingActions = Collections.synchronizedList(new ArrayList<>()); 您使用了错误的数

我有时会从下面的代码中得到以下异常 人们建议,如果我将for循环设置为迭代器,它将解决这个问题。但是我不明白我是不是在删除for循环中的任何元素,而是调用pendingActions.clear;后来 如果有人遇到过这种情况,请告诉我。 另外,如果我向你做一份清单声明,你会考虑吗

private List<Action> pendingActions = Collections.synchronizedList(new ArrayList<>()); 

您使用了错误的数据结构:队列是更好的选择,特别是为并发修改而设计的队列

例如,您可以使用。您可以将其添加到列表中,然后使用添加的操作,如:

Action r;
while ((r = queue.poll()) != null) {
  r.run();
}
使用Collections.synchronizedList无法解决您的问题,至少不能解决自身的问题

使用Collections.synchronizedList包装列表时要记住的一点是,它只为每个单独的方法调用提供互斥,例如,直到对pendingActions.get或pendingActions.iterator的调用返回为止

增强的for循环隐式地创建了一个迭代器;但是,当您迭代该列表时,该列表不会被锁定,无论它是否来自同步列表

您的另一个线程在此迭代期间正在更改列表,并且在您下次尝试从迭代器获取值时仍然会导致ConcurrentModificationException

现在,您可以通过将迭代包装在同步块中,使其在没有CME的情况下工作:

问题是,当列表被迭代时,其他线程将被阻塞。这可能会导致应用程序明显延迟;也可能不是,这取决于调用此方法的频率以及操作运行的时间


但是,使用并发队列完全可以避免这个问题,而且可能比同步列表更快,因为非阻塞并发队列不需要使用完全同步。

您使用的数据结构错误:队列是更好的选择,专门为并发修改而设计的

例如,您可以使用。您可以将其添加到列表中,然后使用添加的操作,如:

Action r;
while ((r = queue.poll()) != null) {
  r.run();
}
使用Collections.synchronizedList无法解决您的问题,至少不能解决自身的问题

使用Collections.synchronizedList包装列表时要记住的一点是,它只为每个单独的方法调用提供互斥,例如,直到对pendingActions.get或pendingActions.iterator的调用返回为止

增强的for循环隐式地创建了一个迭代器;但是,当您迭代该列表时,该列表不会被锁定,无论它是否来自同步列表

您的另一个线程在此迭代期间正在更改列表,并且在您下次尝试从迭代器获取值时仍然会导致ConcurrentModificationException

现在,您可以通过将迭代包装在同步块中,使其在没有CME的情况下工作:

问题是,当列表被迭代时,其他线程将被阻塞。这可能会导致应用程序明显延迟;也可能不是,这取决于调用此方法的频率以及操作运行的时间


但是,使用并发队列可以完全避免该问题,而且可能比同步列表更快,因为非阻塞并发队列不需要使用完全同步。

是否有任何操作在其运行方法中将自身从列表中删除?否,run不会从列表中删除,但在某些竞争条件下,在循环迭代时会执行以下代码/***,以确保仅在OnReuseMe和onPause之间执行操作,否则在应用程序恢复后暂停这些操作以运行。*/private void runNavActionAction{if!canCommitFragmentTransaction{pendingNavActions.addaction;}else{action.run;}您解决了这个问题吗?如果没有,请把跑步方法的内容贴在你的动作课上,虽然还没有固定,但我不会在跑步中触摸列表method@Bulu如果该代码同时运行,则可以解释问题。为什么代码在另一个线程中运行?这些操作是什么?是否有任何操作在其run方法中将自身从列表中移除?否,run不会从列表中移除,但在某些竞争条件下,以下代码在循环迭代时执行/***,以确保仅在onreusime和onPause之间执行操作,否则,在应用程序恢复后暂停运行它们。*/private void runNavActionAction{if!canCommitFragmentTransaction{pendingNavActions.addaction;}else{action.run;}您解决了这个问题吗?如果没有,请把跑步方法的内容贴在你的动作课上,虽然还没有固定,但我不会去碰它
列出内部运行method@Bulu如果该代码同时运行,则可以解释问题。为什么代码在另一个线程中运行?这些行动是什么?谢谢你的回答。我使用了LinkedBlockingQueue,希望它能起作用。我从未能够复制这个问题,但在生产崩溃日志中看到过,我希望最好在Prod中进行测试,并且不应该在使用ArrayList替换LinkedBlockingQueue时引入任何新问题。感谢您给出了很好的答案。我使用了LinkedBlockingQueue,希望它能起作用。我从未能够复制这个问题,但在生产崩溃日志中看到过,我希望最好在Prod中进行测试,并且不应该在用ArrayList替换LinkedBlockingQueue时引入任何新问题
Action r;
while ((r = queue.poll()) != null) {
  r.run();
}
synchronized (pendingActions) {
  for (Action r : pendingActions) {
    r.run();
  }
  r.clear();
}