Java NIO和BIO比较
学过计算机组成原理就知道在IO系统中直接内存访问DMA方式相比程序中断方式访问方式,进一步提高了CPU利用率,这里从Java程序通过对读写一个文件来进行一个验证。
public class TestChanel {
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
FileChannel reader = FileChannel.open(Path.of("Tomcat内核设计剖析.pdf"));
FileChannel writer = FileChannel.open(Path.of("Tomcat内核设计剖析ChannelCopy.pdf"), StandardOpenOption.CREATE, StandardOpenOption.WRITE);
ByteBuffer allocate = ByteBuffer.allocate(1024*1024);
int read = reader.read(allocate);
while (read != 0) {
writer.write(allocate);
read = reader.read(allocate);
}
System.out.println("The channel spend time: " + (System.currentTimeMillis() - start));
reader.close();
writer.close();
start = System.currentTimeMillis();
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("Tomcat内核设计剖析.pdf"));
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("Tomcat内核设计剖析BufferCopy.pdf"));
byte[] bytes = new byte[1024*1024];
read = bufferedInputStream.read(bytes);
while (read != -1) {
bufferedOutputStream.write(bytes);
read = bufferedInputStream.read(bytes);
}
System.out.println("The buffer spend time: " + (System.currentTimeMillis() - start));
bufferedInputStream.close();
bufferedOutputStream.close();
}
}
输出结果为:
The channel spend time: 5
The buffer spend time: 189
这结果确实相差很多,可见NIO读写效率相对传统BIO来说快了很多
NIO读写对象存储在虚拟机中的直接内存,可以使用-XX:MaxDirectMemorySize=Size
参数来限制其大小。
Exception in thread "main" java.lang.OutOfMemoryError: Cannot reserve 1048576 bytes of direct buffer memory (allocated: 8192, limit: 1047552)
at java.base/java.nio.Bits.reserveMemory(Bits.java:178)
at java.base/java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:121)
at java.base/java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:332)
at java.base/sun.nio.ch.Util.getTemporaryDirectBuffer(Util.java:243)
at java.base/sun.nio.ch.IOUtil.read(IOUtil.java:293)
at java.base/sun.nio.ch.IOUtil.read(IOUtil.java:273)
at java.base/sun.nio.ch.FileChannelImpl.read(FileChannelImpl.java:232)
at study.java.nio.TestChanel.main(TestChanel.java:36)
对于这里需要分配1024KB,但如果只分配1023KB就会抛出OutOfMemoryError异常。