简体   繁体   English

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

[英]wait / notifyAll not working as expected

I have a class with two methods, one sends messages, the other confirm the message has been recevied/processed 我有一个带有两种方法的类,一种发送消息,另一种确认消息已被接收/处理

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

When running in a multihread envoirnement (3 thread x 100 req) there are some messages don't wake up from the notify.. 在多线程环境(3线程x 100请求)中运行时,有些消息不会从通知中唤醒。

For example, once all message has been sent 例如,一旦所有消息发送完毕

messageSend = 100
messageRec = 100
messageWake = 98

And the size of the map is 0, There are no repeated messageIds. 映射的大小为0,没有重复的messageIds。

I have shorten the case. 我已经缩短了案子。 It's more complex. 比较复杂。

I have a service that each time a request is received the method send is called. 我有一项服务,每次收到请求时,就会调用send方法。 This method (It's not in the code) send the message to a JMS Queue, other serivice receives this messages, process them and send a response to another JMSQueue, then a JMSConsumer reads the responses and calls the confirm method. 此方法(不在代码中)将消息发送到JMS队列,其他服务接收此消息,对其进行处理并将响应发送到另一个JMSQueue,然后JMSConsumer读取响应并调用Confirm方法。

What is wrong ? 怎么了 ?

You are using wait() wrongly. 您错误地使用了wait()

The wait method should always in a while loop like this: wait方法应始终处于while循环中,如下所示:

synchronized (obj) {
     while (<condition does not hold>)
         obj.wait();
     ... // Perform action appropriate to condition
 }

Suppose Thread1 and Thread2 are waiting. 假设线程1和线程2正在等待。 Thread3 calls notifyAll . Thread3调用notifyAll Thread1 wake up first, and consumes this condition. Thread1首先唤醒,并消耗此条件。 When it comes to Thread2 , Thread2 is supposed to check this condition again, if it is not satisfied, Thread2 should fall into another wait . 说到Thread2,Thread2应该再次检查此条件,如果不满足,则Thread2应该陷入另一个wait

Thanks to james large 多亏了詹姆斯大

The problem is that notifyAll() is called before the wait(). 问题是在wait()之前调用notifyAll()。 The solution is to use a boolean to no wait() if response has been received. 解决方案是,如果已接收到响应,则对不使用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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM