多用户访问此代码时发生java.util.ConcurrentModificationException

多用户访问此代码时发生java.util.ConcurrentModificationException,java,exception-handling,Java,Exception Handling,下面是我的代码抛出java.util.ConcurrentModificationException,它是从servlet执行的 当多个用户尝试访问此代码时发生异常,异常位于此行: 对于(消息消息消息:dayWiseMsgs) 代码: List<Message> newMessages = Collections.synchronizedList( new LinkedList<Message>()); try{ logger.debug("L

下面是我的代码抛出
java.util.ConcurrentModificationException
,它是从servlet执行的

当多个用户尝试访问此代码时发生异常,异常位于此行:

对于(消息消息消息:dayWiseMsgs)

代码:

List<Message> newMessages = Collections.synchronizedList(
        new LinkedList<Message>());

try{

    logger.debug("Last Message Id = " + lastMessageId + 
            " For Chat Room=" + this.getName());

    List<List<Message>> allMessages = new LinkedList<List<Message>>(
            getMessages().values());


    for (List<Message> dayWiseMsgs : allMessages) {
         for(Message msg : dayWiseMsgs){
                    newMessages.add(msg);
                    this.setLastPushMessageId(msg.getId());                 
                }
            }        
        }
    }

    allMessages=null;

} catch(Exception e){
    e.printStackTrace();
}

return newMessages;
List newMessages=Collections.synchronizedList(
新建LinkedList());
试一试{
logger.debug(“Last Message Id=“+lastMessageId+
“对于聊天室=“+this.getName());
List allMessages=新建链接列表(
getMessages().values());
对于(列出DayWiseMSG:allMessages){
对于(消息消息消息:dayWiseMsgs){
newMessages.add(msg);
this.setLastPushMessageId(msg.getId());
}
}        
}
}
allMessages=null;
}捕获(例外e){
e、 printStackTrace();
}
返回新消息;

当遍历列表时,通常会抛出
ConcurrentModificationException
,同时通常会有另一个线程或甚至是同一个循环尝试修改(添加/删除)列表的内容

现在您有了通过调用集合来同步的
新消息的列表。synchronizedList
但是您没有使
所有消息
同步,而是使用
新消息
创建它。

发生在
集合
将被更改时,而一些线程正在使用
迭代器对其进行遍历,在
多线程
以及
单线程
环境中可能发生这种情况

谈到您的代码,当一个线程正在创建
同步的
新消息时,可能会发生这种情况:

List<Message> newMessages = Collections.synchronizedList(
        new LinkedList<Message>()); 
在方法级别移动
synchronized
关键字,如下所示可能适合您:

public synchronized List<Message> test() {
        List<Message> newMessages = new LinkedList<Message>();
        try {
            logger.debug("Last Message Id = " + lastMessageId
                    + " For Chat Room=" + this.getName());
            List<List<Message>> allMessages = new LinkedList<List<Message>>(
                    getMessages().values());
            for (List<Message> dayWiseMsgs : allMessages) {
                if (CollectionUtils.isNotEmpty(dayWiseMsgs)
                        && lastMessageId < dayWiseMsgs.get(
                                dayWiseMsgs.size() - 1).getId()) {
                    for(Message message : dayWiseMsgs){
                        if (message!= null && message.getId() > lastMessageId) {
                            newMessages.add(message);
                            this.setLastPushMessageId(message.getId());
                        }
                    }
                }
            }
            allMessages = null;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return newMessages;
    }

我已经用for循环和synchronized解决了这个问题:

我所做的是:将foreach循环替换为simple for并修改列表的创建,使其同步:

chatRoom.getMessages().put(key, Collections.synchronizedList(new ArrayList<Message>()));



      List<List<Message>> allMessages =new LinkedList<List<Message>>(getMessages().values());

        for (List<Message> dayWiseMsgs : allMessages) {
            //List<Message> dayMsgs = new LinkedList<Message>(dayWiseMsgs);
            if (lastMessageId < dayWiseMsgs.get(dayWiseMsgs.size() - 1).getId()) {
                //for (Message msg : dayWiseMsgs) {
                Message msg = null;
                for(int i =0 ; i < dayWiseMsgs.size() ; i++){
                    msg = dayWiseMsgs.get(i);
                    if (msg.getId() > lastMessageId ) {
                        newMessages.add(msg);
                        this.setLastPushMessageId(msg.getId());

                    }
                }

            }
        }
chatRoom.getMessages().put(key,Collections.synchronizedList(newarraylist());
List allMessages=newlinkedlist(getMessages().values());
对于(列出DayWiseMSG:allMessages){
//List dayMsgs=新链接列表(dayWiseMsgs);
if(lastMessageIdlastMessageId){
newMessages.add(msg);
this.setLastPushMessageId(msg.getId());
}
}
}
}

为什么要在同一个列表中添加
for
循环和
迭代器
?getMessages()的类型是什么?
?它是从多个线程访问/修改的吗?getMessages()这是一个映射,关于这个
列表
它只包含
消息
类,为什么您要再次迭代它?请指定标题-让它更像问题。我尝试了这个解决方案,但仍然出现异常,有一段时间它在同一行抛出NullPointerException:for(消息:dayWiseMsgs)
        <dependency>
            <groupId>commons-collections</groupId>
            <artifactId>commons-collections</artifactId>
            <version>3.2.1</version>
        </dependency>
chatRoom.getMessages().put(key, Collections.synchronizedList(new ArrayList<Message>()));



      List<List<Message>> allMessages =new LinkedList<List<Message>>(getMessages().values());

        for (List<Message> dayWiseMsgs : allMessages) {
            //List<Message> dayMsgs = new LinkedList<Message>(dayWiseMsgs);
            if (lastMessageId < dayWiseMsgs.get(dayWiseMsgs.size() - 1).getId()) {
                //for (Message msg : dayWiseMsgs) {
                Message msg = null;
                for(int i =0 ; i < dayWiseMsgs.size() ; i++){
                    msg = dayWiseMsgs.get(i);
                    if (msg.getId() > lastMessageId ) {
                        newMessages.add(msg);
                        this.setLastPushMessageId(msg.getId());

                    }
                }

            }
        }