繁体   English   中英

如何避免事件驱动中的繁忙 while 循环 Java

[英]How to avoid a busy while loop in event-driven Java

我目前正在以下列方式开发我的事件驱动 Java 软件(这是我的主要方法的本质):

while(true) {
    Event event = eventListener.poll();
    if(event != null) {
        // do something
    } else {
        // do nothing as usual, but burn CPU time.
    }
}

根据我正在构建的内容, eventListener可能正在侦听外部 websocket,轮询 Redis 通道以获取更新,或者等待来自位于同一框的另一个进程的消息(可能通过 UDP/TCP/shm)。

我的想法是,当eventListener返回 null(大部分时间)时,这种繁忙的循环方法会浪费大量 CPU 时间,因为它只是在那里旋转。 但是,除了每次迭代都放置一个Thread.sleep之外,我不知道如何处理这种设计,这不是一个很好的解决方案。

理想情况下,我想要一个方法:

void run(Event event) {
    // do something
}

每当事件命中eventListener时都会调用run 如果没有这样的事件可用,理想情况下,该过程应该只是闲置在那里。

现在,我知道有 websocket 库实际上可以做到这一点,我想知道的是我怎样才能为自己构建这样的东西,并将我的 CPU 从坐在那里浪费自己无所事事中解放出来?

You need to use java non-blocking IO and may be some library that supports high level communication via java NIO (for example netty which supports NIO style communication for HTTP, websockets and redis among many others).

这是一个简短的描述 NIO 是如何工作的。 您正在寻找的是Selector 它允许等待通道上的数据(这是文件或网络连接等的抽象)可用。 这个等待( Selector.select方法)是阻塞的,当一些数据可供读取或 output 缓冲区写入可以获取新数据时,操作系统会恢复该过程。

示意性地,代码如下所示:

Selector selector = createSelector();
Channel channel = createChannelForSocket();

SelectionKey key = channel.register(selector);

while(true) {

  int readyChannels = selector.select(TIMEOUT);

  if(readyChannels == 0) continue;

  Set<SelectionKey> selectedKeys = selector.selectedKeys();

  for(SelectionKey key : selectedKeys) {

    if (key.isReadable()) {
        readDataFromChannel(key.channel())
    } else if (key.isWritable()) {
        writeDataToChannel(key.channel())
    }

  }
}

使用 netty,您有更多高级代码,您可以在其中定义一个Handler程序,该处理程序具有类似void channelRead(ChannelHandlerContext ctx, Object msg)的方法,这是一种读取事件侦听器,您可以实现它来侦听读取事件。

netty 有一个内置循环,看起来类似于上面的示例,但它适用于许多事件侦听器,并将这些事件传播到特定的侦听器。

如果您对大规模使用事件驱动架构感兴趣。 您可能想要使用强大的“事件总线”,例如 Apache Kafka 或 AWS SNS+SQS。 为了更容易,您可以使用 kalium.alkal.io。 这将无缝地处理 POJO 或 protobuf 对象的反序列化。

kalium.on(Event.class, event -> {

   //doSomething with the event
});

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM