簡體   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