【发布时间】:2019-10-10 10:11:41
【问题描述】:
我目前正在以以下方式开发我的事件驱动 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
}
其中run 会在任何时间触发eventListener 时被调用。如果没有这样的事件可用,理想情况下该进程应该只是闲置。
现在,我知道有一些 websocket 库实际上可以做到这一点,我想知道的是如何为自己构建这样的东西,并将我的 CPU 从坐在那里无所事事的浪费中解放出来?
【问题讨论】:
-
最好的方法是实现一个事件传递系统,
poll不需要忙于等待。例如,如果poll归结为select调用一些底层文件句柄(套接字、命名管道等),那么您浪费的 CPU 时间非常少,因为内核知道在它处于休眠状态时让您的进程进入休眠状态。等待一个事件。 -
@JoachimSauer 您是否可以详细说明一下,也许可以举一个简短的例子?我不熟悉 poll 不需要忙等待的事件传递系统。我在帖子中举的例子是我的知识范围。
-
这不是您等待的级别。您需要(例如)将您的套接字通信包装在一个类中,并在套接字读取时进行非忙碌等待。当您在套接字上获得某些东西时,您会生成事件(在您的包装类中),您的应用程序的其他组件可以注册这些事件。
-
@ABC:归根结底,如果您的
poll在某处归结为InputStream.read(),那么这已经不是忙等待:您的进程在等待时不会占用大量 CPU 时间新数据到达。其他机制,例如 NIO/select 允许更多功能(例如同时从多个套接字读取并在 任何 个套接字返回数据时返回),但这并不是绝对必要的。
标签: java design-patterns polling java-11 event-driven