数据报通道、阻塞模式和 CPU



我得到以下代码片段:

datagramChannel = DatagramChannel
    .open(StandardProtocolFamily.INET).setOption(StandardSocketOptions.SO_REUSEADDR, true)
    .setOption(StandardSocketOptions.IP_MULTICAST_IF, networkInterface);
datagramChannel.configureBlocking(true);
datagramChannel.bind(new InetSocketAddress(filter.getType()
    .getPort(filter.getTimeFrameType())));
datagramChannel.join(group, networkInterface);
datagramChannel.receive(buffer);

此代码位于Callable中,我最多创建 12 Callable 秒(因此 12 个线程)以从 12 个不同的端口检索具有不同数据的组播数据包。它每 3-8 秒从网络上的信息中读取一次。

当连续汇集 12 个端口(等待信息、获取信息等)时,它会占用我 100% 的 CPU。

使用 JVisualVM 分析执行,我看到 90% 的执行时间都用于 java.nio.channels.DatagramChannel#receive() ,更准确地说是com.sun.nio.ch.DatagramChannelImpl#receiveIntoBuffer()

  1. 我不太明白为什么阻塞模式会消耗这么多 CPU。

  2. 我已经阅读了一些关于使用 Selector s 而不是阻塞模式的文章,但我真的不明白为什么具有 Selectorwhile (true)会比阻塞通道消耗更少。

问题是您在使用没有选择器的 NIO 时。

没有选择器的NIO可以使用,但是Channel.received会不断尝试读取,这将显示为一个线程的高CPU使用率。

有2种解决方案:-

  • 使用选择器检测是否有要读取的内容。仅当选择器指示有要读取的数据时才调用通道。接收
  • 使用 java.net.DatagramSocket/DatagramPacket 在阻塞模式下发送/接收。

最新更新