代码后产生的ConcurrentModificationException
,确保newMR
在循环中不被修改,mkrs
在并发环境中是线程不安全的。众所周知,List.addAll
是用System.arraycopy
实现的,这是JVM中固有的方法。List.addAll
生成的遍历List.addAll
是否在Java中生成ConcurrentModificationException
?
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)
发布于 2018-07-03 23:59:05
newMR.addAll(mkrs);
在mkrs, mrm.getFooPush()
上迭代。如果在addAll期间更改了该列表,则会收到该消息。
您需要有一个并发安全列表(在getFooPush中)或一个更好的数据结构。与队列类似,如果消息是在末尾添加的,并且您被过滤(在PushRecommend上),则从前端进行过滤。
那就不需要复印了。
如前所述,Collections.synchronizedList(list)
可以使原始数据结构变得安全。
发布于 2018-07-03 05:58:04
javadoc for ArrayList.addAll
声明:
“如果在操作进行期间修改了指定的集合,则此操作的行为是未定义的。”
因此,请考虑一下:
newMR.addAll(mkrs);
addAll
方法必须迭代mkrs
集合。
如果mkrs
在调用addAll(mkrs)
时被另一个线程修改,那么如果mkrs
的类型不是允许同时迭代和更新的并发集合,那么CCME是可能的。
https://stackoverflow.com/questions/51155601
复制