java - 等待 / 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 读取响应并调用确认方法。
怎么了 ?
解决方案
你用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
。
推荐阅读
- node.js - 为什么这个例子会抛出 UnhandledPromiseRejectionWarning?
- julia - 警告:`Array{T, 1}(m::Int) where T` 已被弃用,请改用`Array{T, 1}(undef, m)`。朱莉娅
- codeigniter - 从 url 中删除控制器的名称。代码点火器
- gcc - 如果链接描述文件中没有定义属性部分,有没有办法让编译器发出警告/错误?
- actions-on-google - 如果通过键盘激活操作,则音频不会在 SSML 中播放
- javascript - 反应 API 获取失败
- python - 用字典中的新值替换键值对中的空白值(pythohn 3.x)
- javascript - 根据 id 返回特定的物种
- reactjs - 在 React Native 中仅显示第一行文本
- c# - 当我留在同一页面并单击搜索按钮时,Gridview RowDataBound 不起作用