首页 > 解决方案 > 遍历 List.addAll 生成的 List 会在 Java 中产生 ConcurrentModificationException 吗?

问题描述

下面生成的代码贴ConcurrentModificationExceptionnewMR确保不会在循环中修改,mkrs在并发环境中是线程不安全的。众所周知,JVM中的内在方法List.addAll是由哪个实现的。System.arraycopy遍历是否由Java 中List的生成生成List.addAllConcurrentModificationException

ArrayList<Foo> mkrs = mrm.getFooPush();
ArrayList<Foo> newMR = new ArrayList<Foo>(mkrs.size());
newMR.addAll(mkrs);
for (Foo mkr : newMR) {
    if (mkr != null && mkr instanceof PushRecommend) {
        PushRecommend pr = (PushRecommend) mkr;
        recommendList.add(new MayKnowMessage(pr));
    }
}

发布在 Android 机器上发生的异常堆栈跟踪。请注意,这(ProGuard:433)for (Foo mkr : newMR)写入的行。

java.util.ConcurrentModificationException:
java.util.ArrayList$Itr.next(ArrayList.java:837)
NewFriendManager.void loadNewFriendMsg(boolean)(ProGuard:433)
NewFriendManager.void reloadNewFriendMsg()(ProGuard:308)
NewFriendManager.boolean handleMessage(android.os.Message)(ProGuard:144)
android.os.Handler.dispatchMessage(Handler.java:106)
android.os.Looper.loop(Looper.java:232)
android.os.HandlerThread.run(HandlerThread.java:61)

标签: java

解决方案


状态的javadocArrayList.addAll

“如果在操作进行时修改了指定的集合,则此操作的行为未定义。”

所以考虑一下:

newMR.addAll(mkrs);

addAll方法将不得不迭代mkrs集合。

如果mkrs在您调用 时被另一个线程修改,那么如果 的类型不是允许同时迭代和更新的并发集合addAll(mkrs),则 CCME 是可能的。mkrs


推荐阅读