使用javanio的高效读/写方法

使用javanio的高效读/写方法,java,nio,Java,Nio,假设我们有一个SocketChannel(在非阻塞模式下),它为读取兴趣向选择器注册。假设select()选择器告诉我们该通道已准备好读取,并且我们有一些ByteBuffer。我们想从通道中读取一些字节到这个缓冲区(读取前清除ByteBuffer)。为此,我们使用channel的read()方法返回实际读取的字节数。让我们假设这个数字在从通道读取后是正数,并且ByteBuffer的方法hasRestaining()返回true。在这种情况下,立即尝试从同一频道多读一些内容是否可行? write(

假设我们有一个SocketChannel(在非阻塞模式下),它为读取兴趣向选择器注册。假设select()选择器告诉我们该通道已准备好读取,并且我们有一些ByteBuffer。我们想从通道中读取一些字节到这个缓冲区(读取前清除ByteBuffer)。为此,我们使用channel的read()方法返回实际读取的字节数。让我们假设这个数字在从通道读取后是正数,并且ByteBuffer的方法hasRestaining()返回true。在这种情况下,立即尝试从同一频道多读一些内容是否可行?
write()也有同样的问题。如果write()返回正值,并且缓冲区的所有内容都未发送,那么立即重试直到write()返回零是否可行?

这完全取决于数据到达的数据速率以及应用程序的延迟要求。如果您根本不关心延迟,您可能会通过延迟您的读取兴趣来获得略高的带宽,直到您怀疑有足够的数据到达您的缓冲区

不过你得小心点。延迟读取可能会迫使内核缓冲更多数据,可能会填满其缓冲区,并且必须开始丢弃数据包或进行一些流控制。这将比从最后一段中抹杀任何好处都要严重


所以一般来说,你希望尽可能多地阅读,越早越好。批处理读取的好处充其量是微不足道的,而潜在的陷阱可能是巨大的。请记住,您看到的非完整读取意味着您处理数据的速度比输入数据的速度要快。换言之,您正处于需要消耗CPU的状态,因此较小读取的额外开销基本上是免费的。

这一切都取决于数据到达的数据速率以及应用程序的延迟要求。如果您根本不关心延迟,您可能会通过延迟您的读取兴趣来获得略高的带宽,直到您怀疑有足够的数据到达您的缓冲区

不过你得小心点。延迟读取可能会迫使内核缓冲更多数据,可能会填满其缓冲区,并且必须开始丢弃数据包或进行一些流控制。这将比从最后一段中抹杀任何好处都要严重


所以一般来说,你希望尽可能多地阅读,越早越好。批处理读取的好处充其量是微不足道的,而潜在的陷阱可能是巨大的。请记住,您看到的非完整读取意味着您处理数据的速度比输入数据的速度要快。换言之,您正处于CPU需要消耗的状态,因此较小读取的额外开销基本上是免费的。

如果您得到较短的读取结果,则无需阻塞即可读取更多数据,因此在出现阻塞之前,您不得再次读取。否则,下一次读取几乎肯定会返回零或-1


如果读取填满了缓冲区,从一个连接的角度来看,保持读取直到返回是有意义的如果您得到一个短的读取结果,没有更多的数据可以读取而不阻塞,因此在有数据之前,您不能再次读取。否则,下一次读取几乎肯定会返回零或-1


如果读操作填满了缓冲区,从一个连接的角度来看,保持读操作直到它返回是有意义的,只要您处于非阻塞状态,您应该读/写操作直到返回值为
@veer Yes,我忘了提到所有这些都是关于非阻塞模式的。但是,在返回值为0之前尝试是否真的有效,但未能完全填充缓冲区,是否真的值得再次尝试读取?下一个read()返回正值的概率是否很高?或者正返回值和未完全填充的缓冲区表示我们(很可能)耗尽了内部套接字缓冲区,应该返回到选择?嗯。。。我想你不明白这里发生了什么
ByteBuffer.hasreading
表示您还有空间来填充缓冲区。
read
是否填充缓冲区与从套接字读取所有可用数据不同。@是的,这不一样。但正如我所怀疑的,无法完全填充缓冲区的最可能原因是,当前没有更多的可用数据可从套接字读取(并且新数据将在一段“长”时间后可用,因此我们应该返回选择)。我很想知道这在实践中是真的吗。如果这是真的,我们可以更早地停止读循环,并进行更少的read()调用(不要等待,只要你处于非阻塞状态,你就应该读/写,直到返回值为
@veer是的,我忘了提到所有这一切都是关于非阻塞模式的。但是,在返回值为0但未能完全填充缓冲区之前尝试是否真的有效,是否真的值得立即再次尝试读取?是否有高概率下一个read()是否会返回正值?或者返回正值且缓冲区未满表示我们(很可能)耗尽内部套接字缓冲区并应返回选择?嗯……我认为您不明白这里发生了什么。
ByteBuffer。hasRemaining
表示您还有空间来填充缓冲区。
read
是否填充缓冲区与从套接字读取所有可用数据不同。@veer Yes,这不一样。但正如我所怀疑的,无法完全填充缓冲区的最可能原因是,当前没有更多的可用数据可从套接字读取(并且新数据将在一段“长”时间后可用,因此我们应该返回选择)。我很想知道这在实践中是否真的是真的。如果是真的,我们可以更早地停止读循环,并进行更少的read()调用(不要等待回答!提到缓冲区清除只是为了示例,以澄清缓冲区的初始状态。谢谢