Java 等待/通知所有未按预期工作

Java 等待/通知所有未按预期工作,java,multithreading,concurrency,Java,Multithreading,Concurrency,我有一个类,有两个方法,一个发送消息,另一个确认消息已被接收/处理 public void send(OTAHotelAvailRS otaHotelAvailRS) throws Exception { MessageAvailRs messageAvailRs = new MessageAvailRs(); messageMap.put(messageAvailRs.getMessageId(), messageAvailRs); syn

我有一个类,有两个方法,一个发送消息,另一个确认消息已被接收/处理

   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 thread x 100 req中运行时,有一些消息没有从通知中唤醒

例如,一旦发送了所有消息

messageSend = 100
messageRec = 100
messageWake = 98
并且映射的大小为0,没有重复的MessageID

我已经把箱子缩短了。更复杂

我有一个服务,每次收到请求时,都会调用send方法。此方法不在代码中,它将消息发送到JMS队列,其他服务接收此消息,对其进行处理并向另一个JMSQueue发送响应,然后JMSConsumer读取响应并调用confirm方法

怎么了?

你用错了

wait方法应始终处于while循环中,如下所示:

synchronized (obj) {
     while (<condition does not hold>)
         obj.wait();
     ... // Perform action appropriate to condition
 }
假设Thread1和Thread2正在等待。Thread3调用notifyAll。Thread1首先唤醒,并使用此条件。对于Thread2,Thread2应该再次检查此条件,如果不满足此条件,Thread2应该进入另一次等待。

感谢james large

问题是在等待之前调用notifyAll。解决方案是在收到响应时使用布尔值表示无等待

 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;
}

每条线都做什么?是否有许多线程可能同时调用send和receiveMessage?是的,不同的线程同时调用它们。每次在发球时收到请求时,都会调用send。每次处理消息时,JMS使用者都会调用confirm。我错过了一些与将mesages发送到JMS队列和JMS consumerDamn相关的代码!你是对的。这一定是问题所在。我必须先检查消息是否已收到,然后等待响应。让多线程send在发送消息后确认自己的消息不是简单得多吗?假设发送邮件需要一段时间,您可以使用来清空传出消息队列,这样就不会涉及等待。不存在等待条件。“等待”和“通知”用于同步。如果需要,我建议更改!messageAvailRs.isconfirm为while!正如我在回答中所说,messageAvailRs.isconfirm。