[英]Does traverse List generated by List.addAll produce ConcurrentModificationException in Java?
Code post below produced ConcurrentModificationException
, newMR
is ensured not modified in the loop, mkrs
is thread unsafely in concurrent environment. 后置代号低于生产
ConcurrentModificationException
, newMR
保证不会在环路修改, mkrs
是线程不安全并发环境。 It is known that List.addAll
is implemented by System.arraycopy
which is intrinsic method in JVM. 众所周知
List.addAll
是由System.arraycopy
实现的, System.arraycopy
是JVM中的固有方法。 Does traverse List
generated by List.addAll
produce ConcurrentModificationException
in Java? List.addAll
生成的遍历List
是否在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));
}
}
Post the exception stack trace happened on an Android machine. 发布发生在Android机器上的异常堆栈跟踪。 Note that
(ProGuard:433)
is the line where for (Foo mkr : newMR)
written. 注意
(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)
The javadoc for ArrayList.addAll
states: ArrayList.addAll
的Javadoc状态为:
"The behavior of this operation is undefined if the specified collection is modified while the operation is in progress."
“如果在操作进行过程中修改了指定的集合,则此操作的行为是不确定的。”
So consider this: 所以考虑一下:
newMR.addAll(mkrs);
The addAll
method is going to have to iterate the mkrs
collection. addAll
方法将必须迭代mkrs
集合。
If mkrs
is modified by another thread while you are calling addAll(mkrs)
, then a CCME is possible if the type of mkrs
is not a concurrent collection that allows simultaneous iteration and updates. 如果
mkrs
被另一个线程,而你正在修改调用addAll(mkrs)
那么CCME是可能的,如果类型mkrs
不是并发收集,允许同时进行迭代和更新。
newMR.addAll(mkrs);
iterates over mkrs, mrm.getFooPush()
. 遍历
mkrs, mrm.getFooPush()
。 If that list is changed during the addAll, you get that message. 如果在addAll期间更改了该列表,则会收到该消息。
You need to have a concurrency safe list (inside getFooPush) or a better data structure. 您需要有一个并发安全列表(在getFooPush内部)或更好的数据结构。 Like a queue if the messages are added at the end, and you are filtered (on PushRecommend) consuming from the front.
就像队列一样,如果消息是在末尾添加的,并且您被过滤掉(在PushRecommend上),则从头开始消耗。
Then there is no need to make a copy. 这样就无需进行复制。
As already mentioned, the original data structure could be made safe by Collections.synchronizedList(list)
. 如前所述,可以通过
Collections.synchronizedList(list)
使原始数据结构安全。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.