gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 06:40:23 24 4
gpt4 key购买 nike

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

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

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

我的想法是,当 eventListener 返回 null 时(这是大多数时间),这种繁忙的循环方法会浪费大量 CPU 时间,因为它只是坐在那里旋转。但是,除了每次迭代都放置一个 Thread.sleep 之外,我不知道还有什么其他方法可以实现这种设计,这不是一个很好的解决方案。

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

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

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

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

最佳答案

您需要使用 java non-blocking IO并且可能是一些支持通过 java NIO 进行高级通信的库(例如 netty 支持 HTTP、websockets 和 redis 等的 NIO 样式通信)。

下面是 NIO 工作原理的简短描述。您正在寻找的是 Selector。它允许等到 Channel 上的数据(它是文件或网络连接等的抽象)可用。此等待(Selector.select 方法)是阻塞的,当某些数据可供读取或要写入的输出缓冲区可以获得新数据时,操作系统会恢复该过程。

代码大概是这样的:

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 有一个内置的循环,看起来类似于上面的例子,但对于许多事件监听器来说,它会将这些事件传播给特定的监听器。

关于java - 如何在事件驱动的 Java 中避免繁忙的 while 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58320531/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com