我有一个有两种方法的类,一个发送消息,另一个确认消息已被接收/处理
public void send(OTAHotelAvailRS otaHotelAvailRS) throws Exception {
MessageAvailRs messageAvailRs = new MessageAvailRs();
messageMap.put(messageAvailRs.getMessageId(), messageAvailRs);
synchronized (messageAvailRs) {
messagesSend++;
messageAvailRs.wait();
messageWake++;
}
}
public void confirmMessage(String messageId) {
logger.debug("Confirmed message: " + messageId);
MessageAvailRs messageAvailRs = messageMap.remove(messageId);
if (messageAvailRs != null) {
synchronized (messageAvailRs) {
messageAvailRs.notifyAll();
messagesReceived++;
}
}
}
在多线程安装(3线程x 100 req)中运行时,有些消息不会从通知中唤醒..
例如,一旦发送了所有消息
messageSend = 100
messageRec = 100
messageWake = 98
并且地图的大小为0,没有重复的messageIds。
我缩短了案子。它更复杂。
我有一项服务,每次收到请求时都会调用方法send。此方法(不在代码中)将消息发送到JMS队列,其他服务器接收此消息,处理它们并将响应发送到另一个JMSQueue,然后JMSConsumer读取响应并调用confirm方法。
有什么问题?
答案 0 :(得分:1)
您错误地使用了wait()
。
wait
方法应该始终采用这样的while循环:
synchronized (obj) {
while (<condition does not hold>)
obj.wait();
... // Perform action appropriate to condition
}
假设Thread1和Thread2正在等待。 Thread3调用notifyAll
。 Thread1首先唤醒,并消耗这种情况。当涉及到Thread2时,Thread2应该再次检查这个条件,如果不满足,则Thread2应该落入另一个wait
。
答案 1 :(得分:0)
感谢james large
问题是在wait()之前调用notifyAll()。解决方法是在收到响应时使用boolean to no wait()。
public void send(OTAHotelAvailRS otaHotelAvailRS) throws Exception {
MessageAvailRs messageAvailRs = new MessageAvailRs();
messageMap.put(messageAvailRs.getMessageId(), messageAvailRs);
synchronized (messageAvailRs) {
messagesSend++;
if (!messageAvailRs.isConfirmed()) {
messageAvailRs.wait();
}
messageWake++;
}
}
public void confirmMessage(String messageId) {
logger.debug("Confirmed message: " + messageId);
MessageAvailRs messageAvailRs = messageMap.remove(messageId);
if (messageAvailRs != null) {
meesageAvailRs.confirm();
synchronized (messageAvailRs) {
messageAvailRs.notifyAll();
messagesReceived++;
}
}
}
public synchronized boolean isConfirmed() {
return confimed;
}
public synchronized confirm() {
cofirmed = true;
}