首页 > 解决方案 > 等待 / notifyAll 没有按预期工作

问题描述

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

   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 请求)中运行时,有些消息不会从通知中唤醒。

例如,一旦所有消息都已发送

messageSend = 100
messageRec = 100
messageWake = 98

并且map的大小为0,没有重复的messageIds。

我已经缩短了案例。它更复杂。

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

怎么了 ?

标签: javamultithreadingconcurrency

解决方案


你用wait()错了。

wait方法应始终处于这样的 while 循环中:

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

假设 Thread1 和 Thread2 正在等待。线程 3 调用notifyAll. Thread1 首先唤醒,并消耗这个条件。对于 Thread2 , Thread2 应该再次检查这个条件,如果不满足, Thread2 应该落入另一个wait


推荐阅读