1

我得到以下代码片段:

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);

此代码位于 a 中Callable,我创建了最多 12 个Callables(因此 12 个线程)来检索来自 12 个不同端口的具有不同数据的多播数据包。它只读取每 3-8 秒在网络上广播的信息。

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

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

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

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

4

1 回答 1

1

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

没有 Selector 的 NIO 可以使用,但 Channel.receive 会不断尝试读取显示为一个线程的高 CPU 使用率。

有2个解决方案:-

  • 使用 Selector 来检测是否有要阅读的内容。只有当 Selector 指示有数据要读取时才调用 channel.receive
  • 使用 java.net.DatagramSocket/DatagramPacket 在阻塞模式下发送/接收。
于 2014-11-05T08:14:22.377 回答