2

我是NIO的新手,我发现一篇文章说“基于块的传输通常比基于流的传输更有效”。这意味着 read(ByteBuffer) 是基于块的传输,而 read(byte[]) 是基于流的传输。

我想知道这两种方法的内部区别是什么。

ps:我也听说基于块的传输是传输字节数组,而基于流的传输是逐个传输字节。我认为这是错误的,因为 java.io.FileInputStream.read(byte[]) 也传输字节数组。

4

3 回答 3

3

使 Bytebuffer 更高效的一件事是使用直接内存。这避免了从直接内存复制到字节[]。如果您只是将数据从一个通道复制到另一个通道,则速度可以提高 30%。如果您逐字节读取,则使用 ByteBuffer 可能会稍微慢一些,因为它访问每个字节的开销更大。如果您使用它来读取二进制文件int,或者double它可以更快,因为它可以在一次访问中获取整个值。

于 2013-01-10T08:31:27.947 回答
1

我认为您在谈论buffer-basedstream-basedI/O 操作。JavaNIO是面向缓冲区的,因为首先将数据读入缓冲区,然后再进行处理。这提供了一种灵活性。此外,在处理缓冲区之前,您需要确保缓冲区包含您需要的所有数据。另一方面,使用stream-basedI/O,您从流中读取一个或多个字节,这些字节不会缓存在任何地方。这是一个阻塞 I/O,而buffer-basedI/O(即 Java NIO)是一个非阻塞 IO。

于 2013-01-10T06:33:51.420 回答
0

虽然我不会使用“基于流的”来表征,但在某些情况下, aread(byte[])的效率会有所提高。ByteBufferbyte[]

请参阅关于何时应将直接缓冲区与 Java NIO 用于网络 I/O 的简单规则?ByteBuffer.allocate() 与 ByteBuffer.allocateDirect()

支持 a 的内存ByteBuffer可以(如果“直接”)更容易让 JVM 传递给操作系统并使用 IO 技巧(例如将内存直接传递给读写调用),并且可能不在 JVM 的“上”堆。支持 a 的内存byte[]在 JVM 堆上,并且 IO 通常不会直接进入数组使用的内存(相反,它通常会通过反弹缓冲区 --- 因为 GC 可能会在 IO 时在内存中“移动”数组对象待处理或数组内存可能不连续)。

但是,如果您必须在 Java 中操作数据,aByteBuffer可能没有太大区别,因为您最终必须将数据复制到 Java 堆中才能操作它。如果您在不进行操作的情况下进行数据复制和复制,那么直接 ByteBuffer 可能是一个胜利。

于 2013-01-10T06:32:03.553 回答