下面是我的代码抛出java.util.ConcurrentModificationException
,它正在从servlet执行。
多个用户尝试访问此代码时发生异常,异常就在此行:
for(Message msg: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;
答案 0 :(得分:1)
ConcurrentModificationException当Collection
将被更改而某些线程使用iterator
遍历它时会发生multithreaded
,这可能发生在single threaded
以及newMessages
的情况下环境。
谈到你的代码,当1个线程创建synchronized
List<Message> newMessages = Collections.synchronizedList(
new LinkedList<Message>());
时,就会发生这种情况:
newMessages.add(msg);
而其他人在其中添加元素:
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;
}
关键字可能对您有用:
classpath
在 <dependency>
<groupId>commons-collections</groupId>
<artifactId>commons-collections</artifactId>
<version>3.2.1</version>
</dependency>
:
replace
答案 1 :(得分:0)
在遍历列表时通常抛出ConcurrentModificationException
,同时通常另一个线程甚至同一个循环尝试修改(添加/删除)列表的内容。
现在您已通过调用newMessages
获得了已同步的Collections.synchronizedList
列表
但是你没有使allMessages
同步,你使用newMessages
创建它。
答案 2 :(得分:0)
我使用for循环和synchronized来解决它:
我所做的是:用简单的for替换foreach循环并修改list的创建,使其同步:
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());
}
}
}
}