处理大量有状态事件的Java最佳实践

处理大量有状态事件的Java最佳实践,java,events,concurrency,event-handling,threadpool,Java,Events,Concurrency,Event Handling,Threadpool,我正在寻找一个实用程序类或最佳实践模式来处理应用程序中大量传入的有状态事件 想象一下,一个生产者产生了许多事件,然后这些事件被处理这些事件的应用程序使用。现在,在某些情况下,生产者产生的事件比消费者实际能够处理的要多,但由于所有事件都是有状态的,因此某些事件是否会丢失并不重要,因为最新的事件包含以前事件传递的所有信息 我现在已经编写了以下java代码来处理这些情况,但我不确定这是否是正确的方法,也不确定是否有更简单、更好、更安全的方法 private static ScheduledThread

我正在寻找一个实用程序类或最佳实践模式来处理应用程序中大量传入的有状态事件

想象一下,一个生产者产生了许多事件,然后这些事件被处理这些事件的应用程序使用。现在,在某些情况下,生产者产生的事件比消费者实际能够处理的要多,但由于所有事件都是有状态的,因此某些事件是否会丢失并不重要,因为最新的事件包含以前事件传递的所有信息

我现在已经编写了以下java代码来处理这些情况,但我不确定这是否是正确的方法,也不确定是否有更简单、更好、更安全的方法

private static ScheduledThreadPoolExecutor executorService = new ScheduledThreadPoolExecutor(1);
private final static Object lock = new Object();
private static List<EventData> lastEventData = null;

static {
    executorService.scheduleWithFixedDelay(new Runnable() {
        @Override
        public void run() {
            synchronized(lock) {
                while(lastEventData == null && !executorService.isShutdown()) {
                    try {
                        lock.wait();
                    } catch (InterruptedException ex) { ... }
                }
                try {
                    actUponEvent(lastEventData);
                } catch (Throwable ex) { ... }
                lastEventData = null;
            }
        }
    }, 250, 250, TimeUnit.MILLISECONDS);
}


public synchronized update(final List<EventData> data) {
    synchronized(lock) {
        lastEventData = data;
        lock.notifyAll();
    }
}

public void dispose() {
    executorService.shutdown();
}
private static ScheduledThreadPoolExecutor executor service=new ScheduledThreadPoolExecutor(1);
私有最终静态对象锁=新对象();
私有静态列表lastEventData=null;
静止的{
executorService.scheduleWithFixedDelay(新的Runnable(){
@凌驾
公开募捐{
已同步(锁定){
while(lastEventData==null&&!executorService.isshutton()){
试一试{
lock.wait();
}catch(InterruptedException ex){…}
}
试一试{
ActupOneEvent(lastEventData);
}捕获(可丢弃的ex){…}
lastEventData=null;
}
}
},250,250,时间单位为毫秒);
}
公共同步更新(最终列表数据){
已同步(锁定){
lastEventData=数据;
lock.notifyAll();
}
}
公共空间处置(){
executorService.shutdown();
}
换句话说,我希望在事件到达后尽快收到事件通知,但速率限制为每250ms一个事件,我只对最后一个传入事件感兴趣


我在java.util.concurrent中查找了一些提示/预先存在的解决方案,但找不到任何适合我的问题的方法。BlockingQueue一开始看起来很不错,因为它会在空时阻塞,但另一方面,队列本身对我来说并不重要,因为我只对最新的事件感兴趣,而插入时阻塞(如果已满)也不是我想要的。

以下模型可以支持非常高的更新率,(每秒数以千万计)但您只需在内存中保留最新的


如果每N毫秒拍摄一次快照,则可以使用此方法

final AtomicReference<ConcurrentHashMap<Key, Event>> mapRef =
这种映射方式具有任何关键点的最新更新

有一个每N毫秒运行一次的任务。此任务运行时可以将地图替换为另一个(或以前的空地图,以避免创建新地图)

ConcurrentMap prev=mapRef.set(prevEmptyMap);
对于(事件e:prev.values())
过程(e);
prev.clear();
this.prevEmptymap=prev;

您能否详细说明一下使用者线程的确切外观。我不确定如何让使用者线程等待传入事件。有时可能会有较长时间(分钟、小时)没有事件,有时会有大量事件(每秒100秒)。我想你说过它每250毫秒运行一次,所以它不等待事件,它每250毫秒运行一次。如果这不是你的意思,你能澄清一下你的要求是什么吗?每秒100秒不是很高,你应该能够通过简单的队列来支持这一点。如果你有大约10公里到10米的每秒,那么你真的需要上面的地图。在在上面我发布的示例中,我每250毫秒运行一个线程,如果没有要处理的传入事件,则等待直到新事件到来并立即处理它。在线程结束并再次通过250毫秒后,我将启动下一个线程,依此类推。使用普通队列是什么意思?我不想要任何基于FIFO的队列,而是需要一个仅存储一个事件的队列,在消费者端阻塞,但在生产者端不阻塞。因此,您需要等待250毫秒,然后立即处理下一个事件,然后再等待250毫秒,然后再等待一个事件?因此,一个事件通过得很快,而中间的每个事件可能需要等待250毫秒?我没有说您需要queue或非阻塞消费者,我只是说这不会造成真正的区别。;)是的,你是对的,如果每秒少于4个事件,每个事件都将立即处理,但如果更多,我会将事件数量限制为每秒4个(1000/250),但只取最后一个传入事件并丢弃所有其他事件(我不需要它们)。有没有比我更了解并发性的人可以看看代码,告诉我它是否真的有意义,以及可能的陷阱?
Key key = keyFor(event);
mapRef.get().put(key, event);
ConcurrentMap<Key, Event> prev = mapRef.set(prevEmptyMap);

for(Event e: prev.values())
    process(e);
prev.clear();
this.prevEmptymap = prev;