[英]Java: How can I put a time limit on a class that collects event msgs, when an event is, in fact, missing
I want to find a way to prevent a 'collector' class from waiting forever, because its contents are incomplete, and it has no way to know that the missing event msg(s) don't exist to be passed to it.我想找到一种方法来防止“收集器”class 永远等待,因为它的内容不完整,并且它无法知道丢失的事件 msg(s) 不存在传递给它。
I have an class named EventSet that has related event msgs (from monitoring) passed to it from a JMS onMessage listener.我有一个名为 EventSet 的 class ,它具有从 JMS onMessage侦听器传递给它的相关事件消息(来自监视)。 Each related event has a seq no and the last event is called 'TxnEnd' - this has the highest seq-no.每个相关事件都有一个 seq no,最后一个事件称为“TxnEnd” - 这具有最高的 seq-no。 When the total of event msgs is equal the seq-no of TxnEnd, I know all events are present and my code instructs the callback class to process the set of events.当事件消息的总数等于 TxnEnd 的 seq-no 时,我知道所有事件都存在,并且我的代码指示回调 class 处理事件集。
When there is a missing event, that instance of EventSet sits there patiently waiting for ever.当缺少事件时,EventSet 的实例会耐心地等待。
My idea to solve this is to somehow set a limit on the wait time, at the point when the Class is created.我解决这个问题的想法是在创建 Class 时以某种方式设置等待时间的限制。 When that is exceeded, my code should instruct the callback to handle the incomplete set of events.当超出时,我的代码应该指示回调处理不完整的事件集。
I have spent mich time on two previous occasions, over the pst 2/3 months, trying this and that, based on suggestions and ideas - without success.在 pst 2/3 个月的时间里,我曾两次根据建议和想法尝试这个和那个,但没有成功。 Until now, it's been possible to park this as it almost never happens.到现在为止,这是可以停车的,因为它几乎从未发生过。 Now, I do need to solve it.现在,我确实需要解决它。
In essence, it seems like a reasonably common situation which should have a straight forward solution.从本质上讲,这似乎是一种相当普遍的情况,应该有一个直接的解决方案。 I have failed to find one.我没能找到一个。
I will be gratreful for any suggestions or solutions.对于任何建议或解决方案,我将不胜感激。
I dont' know if your libraries support this approach, but a plain Java attempt would look something like this:我不知道您的库是否支持这种方法,但简单的 Java 尝试看起来像这样:
public class MessageProcessor extends Thread {
private static final long PROCESSOR_TIMEOUT = 3600 * 1000 /* 1 hour? */;
private static final long ONE_MESSAGE_TIMEOUT = 1000 /* 1 sec? */;
private long m_startTime = 0;
public void startProcessing() {
m_startTime = System.currentTimeMillis();
start();
}
@Override
public void run() {
while(true) {
// ---------------------------------
// check abort condition
// ---------------------------------
if(System.currentTimeMillis() - m_startTime > PROCESSOR_TIMEOUT) {
break;
}
// ---------------------------------
// handle 1 message (with timeout)
// ---------------------------------
try {
// pseudo code
collectOneMessage(ONE_MESSAGE_TIMEOUT);
}
catch(InterruptedException e) {
// ignoring timeout exception
}
}
// ---------------------------------
// finish up
// ---------------------------------
// ...
}
}
The solution was to use a Timer and a TimerTask (as an inner class).解决方案是使用 Timer 和 TimerTask(作为内部类)。 The constructor creates the Timer and schedules the TimerTask for the required number of seconds, If all related events are received, the callback is invoked and the timer is cancelled.构造函数创建 Timer 并将 TimerTask 调度为所需的秒数,如果收到所有相关事件,则调用回调并取消计时器。 In the rare cases where an event is missing, the TimerTask kicks in and sends an incomplete set of events to the callback and logs an error.在缺少事件的极少数情况下,TimerTask 会启动并将一组不完整的事件发送到回调并记录错误。
FYI.供参考。
public class EventSet {公共 class 事件集 {
private MonitorEventsConsumer eventsConsumer;
// For timeout handling
private Timer timer;
private int waitTime; // seconds to wait
protected boolean isComplete;
private String localTxnId;
String eventSourceAddress;
private boolean txnEndReceived;
private int maxCounter = 0;
private List<String> monEvents = new ArrayList<>();
public EventSet(String localTxnId) {
this(localTxnId, 20); // Default the waiting time for all events to be received to 20 secs
}
public EventSet(String localTxnId, int waitTime) {
this.localTxnId = localTxnId;
timer = new Timer();
this.waitTime = waitTime;
timer.schedule(new TimeoutTask(), waitTime*1000);
}
public boolean isNew() {
return monEvents.isEmpty();
}
public void addEvent(String eventAsXML) {
monEvents.add(eventAsXML);
String counter = StringUtils.substringBetween(eventAsXML, "wmb:counter=\"", "\"/>");
eventSourceAddress = StringUtils.substringBetween(eventAsXML, " wmb:eventSourceAddress=\"", "\">");
if (eventSourceAddress.endsWith("transaction.End")) {
txnEndReceived = true;
}
int iCounter = Integer.parseInt(counter);
if (iCounter > maxCounter) {
maxCounter = iCounter;
}
if (txnEndReceived && maxCounter == monEvents.size()) {
// all events should have been received unless maxCounter = 1
// Call back to the onMessageHandler to process this event set.
eventsConsumer.sendEventsToNjams(localTxnId, this);
isComplete = true;
timer.cancel();
}
}
public List<String> getMonEvents() {
return monEvents;
}
public void clear() {
monEvents.clear();
localTxnId = null;
isComplete = false;
maxCounter = 0;
}
public void registerHandler(final MonitorEventsConsumer eventsConsumer) {
if (this.eventsConsumer == null) {
this.eventsConsumer = eventsConsumer;
}
}
class TimeoutTask extends TimerTask {
public void run() {
eventsConsumer.sendEventsToNjams(localTxnId, EventSet.this);
isComplete = true;
System.err.println(String.format("Message events for local txn id '%s' were incomplete after waiting for %d seconds. they were sent to nJAMS in this state", localTxnId, waitTime));
timer.cancel(); //Terminate the timer thread
}
}
} }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.