作者:聂勇 欢迎转载,请保留作者信息并说明文章来源!
之前写了一篇文章《NIO入门篇》,介绍了NIO的缓冲区与旧IO流操作的不同以及如何使用缓冲区。Java封装了非常多的细节,为了跨平台,操作系统许多的特性我们无法使用,如内存映射。JDK1.4增加了NIO,使得我们可以在Java中使用文件锁、内存映射等特性。
下面就缓冲区操作原理和实现、内存映射原理和实现进行介绍和比较。
缓冲区操作
其实缓冲区的操作可能理解为:应用将数据写入缓冲区,然后整个缓存区写入磁盘(输出);从磁盘读取数据,填满缓存区,应用从缓存区读取数据(输入)。
以读操作为例:用户进程调用操作系统的read()方法,要求填充缓冲区。内核向磁盘控制器发指令,要求从磁盘读取数据。磁盘控制器从磁盘读取所需数据填充内核的缓冲区(现代操作系统中,这一步是由DMA完成,无需主CPU协助),一旦所需的数据读取完毕,内核将内核缓冲区的数据复制到用户进程的缓冲区。
Java示例代码:
内存映射
将文件的某一部分或全部映射到一个内存区域,用操作内存的方式操作文件。和传统的read()方法操作相比,有如下不同点:
- 用户进程直接把文件当内存操作,不需调用系统的read()方法。
- 用户进程读取内存映射空间,如果没有数据,会自动产生页错误,从文件将数据读入内存区。
- 避免了内核空间和用户空间之间的数据复制,更加高效。
- 节省内存。
Java示例代码:
性能比较
测试环境:
操作系统:Windows 7 64位
CPU:Intel(R) Core(TM) i3 CPU M 380 @2.53GHz 2.53GHz
内存:6GB
硬盘:5400转
分别执行上面的两段代码,结果如下:
2013-9-29 18:24:52 cn.aofeng.demo.nio.BufferIO main
信息: 缓冲区读取文件耗时:32463毫秒
|
|
2013-9-29 18:18:20 cn.aofeng.demo.nio.MemoryMapper main
信息: 内存映射读取文件耗时:27956毫秒,文件长度:2006157134字节