Java基础-虚拟内存之映射字节缓冲区(MappedByteBuffer)
作者:尹正杰
版权声明:原创作品,谢绝转载!否则将追究法律责任。
一.映射字节缓冲区
1>.什么是虚拟内存
答:虚拟是的一种技术。它使得认为它拥有连续的可用的(一个连续完整的),而实际上,它通常是被分隔成多个碎片,还有部分暂时存储在外部上,在需要时进行。目前,大多数操作系统都使用了虚拟内存,如Windows家族的“虚拟内存”;Linux的“交换空间”等。
2>.什么是映射字节缓冲区
答:映射字节缓冲区,说白了就是Java将磁盘中的文件映射到内存中,然后通过修改内存的数据,从而间接修改了磁盘中的文件。这样做的目的就是为了快速对磁盘中的文件就行修改操作,将原来在磁盘上的I/O操作转换成了内存的I/O操作!
3>.Java代码案例展示
准备文件数据如下:
执行以下代码:
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 package cn.org.yinzhengjie.nio; 7 8 import java.io.RandomAccessFile; 9 import java.nio.MappedByteBuffer;10 import java.nio.channels.FileChannel;11 12 public class MyMapFileBuffer {13 public static void main(String[] args) throws Exception {14 testMapFileBuffer();15 }16 17 public static void testMapFileBuffer() throws Exception {18 //随机访问文件19 RandomAccessFile raf = new RandomAccessFile("D:\\BigData\\JavaSE\\yinzhengjieData\\1.txt" , "rw") ;20 //源文件通道,由于我们的raf对象是随机访问文件,因此我们就通过它来进行读写操作。21 FileChannel fc = raf.getChannel();22 23 //调用FileChannel的映射功能,指定映射模式为读写,指定映射的其实位置是0,结束位置是3(不包含3),因此我们只能修改索引为0,1,2的映射字符,如果超出映射范围就会抛异常:BufferOverflowException24 MappedByteBuffer buf = fc.map(FileChannel.MapMode.READ_WRITE , 0 , 3) ;25 buf.put((byte)89) ;26 buf.put((byte)73) ;27 buf.put((byte)78) ;28 System.out.println("修改完成!");29 }30 }31 32 /*33 以上代码输出结果如下:34 修改完成!35 */
查看磁盘中文件内容如下:
二.向文件写入10w次数据,使用RandomAccessFile方式和MappedByteBuffer方式对比性能
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
尹正杰
1 /* 2 @author :yinzhengjie 3 Blog:http://www.cnblogs.com/yinzhengjie/tag/Java%E5%9F%BA%E7%A1%80/ 4 EMAIL:y1053419035@qq.com 5 */ 6 package cn.org.yinzhengjie.nio; 7 8 import java.io.RandomAccessFile; 9 import java.nio.MappedByteBuffer;10 import java.nio.channels.FileChannel;11 12 public class MyMapFileBuffer {13 final static byte[] data = {89,73,78};14 15 public static void main(String[] args) throws Exception {16 testMapFileBuffer();17 testRandomAccessFile();18 }19 20 public static void testRandomAccessFile() throws Exception{21 //随机访问文件22 RandomAccessFile raf = new RandomAccessFile("D:\\BigData\\JavaSE\\yinzhengjieData\\1.txt" , "rw") ;23 long start = System.currentTimeMillis();24 for (int i=0 ;i<100000;i++){25 raf.write(data);26 //每次写完数据将文件指针回到原点27 raf.seek(0);28 }29 long end = System.currentTimeMillis();30 System.out.printf("RandomAccessFile 方式写入10万次数据需要用时为:[%d]\n",(end-start));31 }32 33 34 public static void testMapFileBuffer() throws Exception {35 //随机访问文件36 RandomAccessFile raf = new RandomAccessFile("D:\\BigData\\JavaSE\\yinzhengjieData\\1.txt" , "rw") ;37 //源文件通道,由于我们的raf对象是随机访问文件,因此我们就通过它来进行读写操作。38 FileChannel fc = raf.getChannel();39 40 //调用FileChannel的映射功能,指定映射模式为读写,指定映射的其实位置是0,结束位置是3(不包含3),因此我们只能修改索引为0,1,2的映射字符,如果超出映射范围就会抛异常:BufferOverflowException41 MappedByteBuffer buf = fc.map(FileChannel.MapMode.READ_WRITE , 0 , 3) ;42 long start = System.currentTimeMillis();43 for (int i=0;i<100000;i++){44 //往虚拟内存中写入数据45 buf.put(data);46 //启用整个容量47 buf.clear();48 }49 long end = System.currentTimeMillis();50 System.out.printf("MapFileBuffer 方式写入10万次数据需要用时为:[%d]\n",(end-start));51 }52 }53 54 /*55 以上代码输出结果如下:56 MapFileBuffer 方式写入10万次数据需要用时为:[7]57 RandomAccessFile 方式写入10万次数据需要用时为:[196]58 */