简体   繁体   English

Java:当一个事件实际上丢失时,如何对收集事件消息的 class 设置时间限制

[英]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.

相关问题 我怎么知道实例变量何时在Java中引发事件? - How can I know when an instance variable raise a event in java? Java子类如何响应超类中的事件? - How can a Java sub class respond to an event in the super class? 如何在Spinner对象中使用自定义Spinner类每次触发OnItemSelectedListener事件 - How can I use custom Spinner class in spinner object to fire OnItemSelectedListener event every-time 如何使用实现类的方法来捕获Java中的事件? - How method from implement class can be used to catch event in Java? 当传感器事件发生变化时,如何多次增加变量? - How can I increment the variable more than one time when sensor event changed? 如何使用bankSim类中的Event类方法? - How can I utilize my Event class methods in bankSim class? Java applet无法加载时,我可以捕获事件吗? - Can I capture an event when a Java applet fails to load? 流口水:在一段时间内针对组中的每个事实触发一个事件 - Drools: fire one event for each fact in group over time window 当 Java jsp 中的输入发生键事件时,如何隐藏警报 div - How can I hide an alert div when key-event on input in Java jsp 如何获取Android日历中事件的开始时间 - How can I get the start time of an event in the android calendar
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM