我刚接触 NIO ,我发现一篇文章说'基于块的传输通常比基于流的传输更有效'。 这意味着read(ByteBuffer)是基于块的传输,read(byte [])是基于流的传输。
我想知道两种方法之间的内在差异。
ps:我也听说基于块的传输正在传输字节数组,而基于流的传输正在逐个传输字节。我认为这是错的, 因为java.io.FileInputStream.read(byte [])也传输字节数组。
答案 0 :(得分:3)
使Bytebuffer更有效的一件事是使用直接内存。这样可以避免从直接内存复制到byte []。如果您只是将数据从一个频道复制到另一个频道,则速度可提高30%。如果逐字节读取,使用ByteBuffer可能会稍慢,因为它有更多的开销访问每个字节。如果你用它来读取二进制文件,例如int
或double
它可以更快,因为它可以在一次访问中获取整个值。
答案 1 :(得分:1)
我认为您在谈论buffer-based
与stream-based
I / O操作。 Java NIO
是面向缓冲区的,因为数据首先被读入缓冲区然后被处理。这提供了一种灵活性。此外,在处理缓冲区之前,您需要确保缓冲区包含您需要的所有数据。另一方面,使用stream-based
I / O,您从流中读取一个或多个字节,这些字节不会缓存在任何位置。这是阻塞I / O,而buffer-based
I / O(Java NIO)是非阻塞IO。
答案 2 :(得分:0)
虽然我不会使用“基于流”来表征read(byte[])
,但在某些情况下,ByteBuffer
的效率会提高byte[]
。
请参阅A simple rule of when I should use direct buffers with Java NIO for network I/O?和ByteBuffer.allocate() vs. ByteBuffer.allocateDirect()
支持ByteBuffer
的内存可以(如果“直接”)更容易让JVM传递给操作系统并执行IO技巧(例如直接将内存传递给读写调用),以及可能不在JVM的堆上。支持byte[]
的内存位于JVM堆上,IO通常不会直接进入阵列使用的内存(而是经常通过反弹缓冲区---因为GC可能会“移动”数组对象在IO处于挂起状态或数组内存可能不连续的情况下在内存中。
但是,如果你必须在Java中操作数据,ByteBuffer
可能没什么区别,因为你最终必须将数据复制到Java堆中来操纵它。如果你正在进行数据拷贝进行操作,那么直接ByteBuffer就可以获胜。