FAQ(80):java.util.ConcurrentModificationException at java.util.ArrayList$Itr.checkForComodification

本文解析了一个并发场景下遍历并删除列表元素时出现的ConcurrentModificationException异常。通过具体代码示例展示了错误的原因,并提供了正确的解决方案,强调了在迭代过程中避免直接修改集合的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

2018年8月31日

1、日志:

2018-04-13 20:00:55.757:WARN:oejs.ServletHandler:/g01-web/admin/activityManager/sendActivity.jsp
java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
	at java.util.ArrayList$Itr.next(ArrayList.java:831)
	at org.apache.jsp.admin.activityManager.sendActivity_jsp._jspService(sendActivity_jsp.java:146)
	at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:111)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
	at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:403)
	at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:492)
	at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:378)
	at javax.servlet.http.HttpServlet.service(HttpServlet.java:848)
	at org.eclipse.jetty.servlet.ServletHolder.handle(ServletHolder.java:684)
	at org.eclipse.jetty.servlet.ServletHandler.doHandle(ServletHandler.java:501)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:137)
	at org.eclipse.jetty.security.SecurityHandler.handle(SecurityHandler.java:557)
	at org.eclipse.jetty.server.session.SessionHandler.doHandle(SessionHandler.java:231)
	at org.eclipse.jetty.server.handler.ContextHandler.doHandle(ContextHandler.java:1086)
	at org.eclipse.jetty.servlet.ServletHandler.doScope(ServletHandler.java:428)
	at org.eclipse.jetty.server.session.SessionHandler.doScope(SessionHandler.java:193)
	at org.eclipse.jetty.server.handler.ContextHandler.doScope(ContextHandler.java:1020)
	at org.eclipse.jetty.server.handler.ScopedHandler.handle(ScopedHandler.java:135)
	at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:116)
	at org.eclipse.jetty.server.Server.handle(Server.java:370)
	at org.eclipse.jetty.server.AbstractHttpConnection.handleRequest(AbstractHttpConnection.java:494)
	at org.eclipse.jetty.server.AbstractHttpConnection.content(AbstractHttpConnection.java:982)
	at org.eclipse.jetty.server.AbstractHttpConnection$RequestHandler.content(AbstractHttpConnection.java:1043)
	at org.eclipse.jetty.http.HttpParser.parseNext(HttpParser.java:865)
	at org.eclipse.jetty.http.HttpParser.parseAvailable(HttpParser.java:240)
	at org.eclipse.jetty.server.AsyncHttpConnection.handle(AsyncHttpConnection.java:82)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint.handle(SelectChannelEndPoint.java:667)
	at org.eclipse.jetty.io.nio.SelectChannelEndPoint$1.run(SelectChannelEndPoint.java:52)
	at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:608)
	at org.eclipse.jetty.util.thread.QueuedThreadPool$3.run(QueuedThreadPool.java:543)
	at java.lang.Thread.run(Thread.java:745)

 

2、解决方法:


1)线程的bug;
源码:
(在遍历对象时,同时修改对象的数据)

        for(ActivityInfo info : list){
            if(info.getActivityId() == Integer.parseInt(activityId)){
                System.out.println("del-info:"+info);
                list.remove(info);
                accountService.notifyLogonPlayerActivity(ActivityNotifyType.FORCE_ACTIVITY.getCode(),info.getActivityId());
                break;
            } 
        }

 

2)修改:

        for(ActivityInfo info : list){
            if(info.getActivityId() == Integer.parseInt(activityId)){
                System.out.println("del-info:"+info);
                delActivity = info;
                accountService.notifyLogonPlayerActivity(ActivityNotifyType.FORCE_ACTIVITY.getCode(),info.getActivityId());
                break;
            } 
        }
        list.remove(delActivity); 

改为:跳出循环体后再修改对象。

 

3)foreach的快速失败,

阿里巴巴java开发手册建议:


7. 【强制】不要在 foreach 循环里进行元素的 remove / add 操作。 remove 元素请使用 Iterator
方式,如果并发操作,需要对 Iterator 对象加锁。


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

后台技术汇

对你的帮助,是对我的最好鼓励。

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值