package io; import java.io.File; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * Java NIO(内存映射文件) 与 传统IO 读取 性能测试 * * 读取 RandomAccessFile 类读写测试及其性能优化(一) * (链接 http://jackyin5918.iteye.com/blog/2022888 )中 * GenerateIntArray 生成的并保存到文件的数据. * 测试时读取1千万个整型构成的二进制文件38.1M * * 由测试结果分析可知: * * readData(f) -- 普通IO方式读取 * readDataNIO(f) -- NIO Channel,Buffer方式读取 * readDataNIO_D(f) -- NIO中Buffer使用 直接方式分配空间(allocateDirect) * readDataMap_M(f) -- 多线程中使用 内存映射文件 * readDataMap(f) -- 单线程中使用内存映射文件读取 * * NIO方式使用直接分配Buffer空间方式读取性能最好,甚至超过了内存映射文件 * (可能是文件还不够大,如果文件达到1000M以上应该是内存映射文件性能最好). * * 普通NIO方式 耗时 是NIO_D方式的2倍. * * 传统IO方式读取文件,耗时 是NIO的 上百倍. * * 内存映射文件,在文件较大(大小达到几十M时)可以显著提升性能. * 多线程中使用内存映射文件 没有 提高性能. ----------------------测试结果--------- count = 1000, size = 10000 正在读取数据,请稍后... readData(f) 读取数据成功, 耗时:411326 正在读取数据,请稍后... readDataNIO_D(f) 读取数据成功, 耗时:4161 正在读取数据,请稍后... readDataNIO(f) 读取数据成功, 耗时:10645 正在读取数据,请稍后... readDataMap_M(f) 读取数据成功, 耗时:6682 正在读取数据,请稍后... readDataMap 读取数据成功, 耗时:4841 */ public class GetTheMiddle { private int count = 10; // 数组的个数, private int size = 1000; // 每个数组的元素个数 private int[][] dataArr; public GetTheMiddle() { dataArr = new int[count][size]; } public GetTheMiddle(int count, int size) { this.count = count; this.size = size; this.dataArr = new int[count][size]; } public int[][] getDataArr() { return dataArr; } public int[][] readData(File f) { try { RandomAccessFile rf = new RandomAccessFile(f, "r"); for (int i = 0; i < count; i++) { for (int j = 0; j < size; j++) { dataArr[i][j] = rf.readInt(); } } rf.close(); } catch (Exception e) { e.printStackTrace(); } return dataArr; } public int[][] readDataNIO(File f) { try { RandomAccessFile rf = new RandomAccessFile(f, "r"); FileChannel fc = rf.getChannel(); ByteBuffer buffer = ByteBuffer.allocate(size * 4); for (int i = 0; i < count; i++) { fc.read(buffer); buffer.rewind(); for (int j = 0; j < size; j++) { dataArr[i][j] = buffer.getInt(); } buffer.rewind(); } rf.close(); } catch (Exception e) { e.printStackTrace(); } return dataArr; } public int[][] readDataNIO_D(File f) { try { RandomAccessFile rf = new RandomAccessFile(f, "r"); FileChannel fc = rf.getChannel(); ByteBuffer buffer = ByteBuffer.allocateDirect(size * 4); for (int i = 0; i < count; i++) { fc.read(buffer); buffer.rewind(); for (int j = 0; j < size; j++) { dataArr[i][j] = buffer.getInt(); } buffer.rewind(); } rf.close(); } catch (Exception e) { e.printStackTrace(); } return dataArr; } public int[][] readDataMap(File f) { try { RandomAccessFile rf = new RandomAccessFile(f, "r"); FileChannel fc = rf.getChannel(); int mapSize = size * 4; for (int i = 0; i < count; i++) { int position = i * size * 4; MappedByteBuffer mBuffer = fc.map(MapMode.READ_ONLY,position,mapSize); for (int j = 0; j < size; j++) { dataArr[i][j] = mBuffer.getInt(); } } rf.close(); } catch (Exception e) { e.printStackTrace(); } return dataArr; } class ReadDataTask implements Runnable { private File f; private int dataIndex; public ReadDataTask(File f,int dataIndex) { this.f = f; this.dataIndex = dataIndex; } @Override public void run() { try { RandomAccessFile rf = new RandomAccessFile(f, "r"); FileChannel fc = rf.getChannel(); int mapSize = size * 4; int position = dataIndex * size * 4; MappedByteBuffer mBuffer = fc.map(MapMode.READ_ONLY,position,mapSize); for (int j = 0; j < size; j++) { dataArr[dataIndex][j] = mBuffer.getInt(); } rf.close(); } catch (Exception e) { e.printStackTrace(); } } } public int[][] readDataMap_M(File f) { try { ExecutorService exec = Executors.newCachedThreadPool(); for(int i=0;i<count;i++) { exec.execute(new ReadDataTask(f,i)); } exec.shutdown(); while(true) { if(exec.isTerminated()) break; } } catch (Exception e) { e.printStackTrace(); } return dataArr; } public static void main(String[] args) { int count = 1000; int size = 10000; boolean bPrintData = false; // 是否打印生成的数组,当数据量大是不打印,只在小数据量时打印以便测试 boolean bRefreshData = true; //是否重新生成数据,第一次测试时生成数据后,改成false不必重新生成数据 System.out.printf("count = %d, size = %d \n\n", count, size); GetTheMiddle gm = new GetTheMiddle(count,size); GenerateIntArray generator = new GenerateIntArray(count, size); File f; try { f = new File("D:\\D\\test_data.dat"); if(bRefreshData) { generator.refreshDataArr(); generator.writeData2File_B(f); } System.out.println("正在读取数据,请稍后..."); long startTmie = System.nanoTime(); gm.readData(f); long totalTime = (System.nanoTime() - startTmie)/ 100000; System.out.println("readData(f) 读取数据成功, 耗时:" + totalTime); System.out.println(); System.out.println("正在读取数据,请稍后..."); startTmie = System.nanoTime(); gm.readDataNIO_D(f); totalTime = (System.nanoTime() - startTmie)/ 100000; System.out.println("readDataNIO_D(f) 读取数据成功, 耗时:" + totalTime); System.out.println(); System.out.println("正在读取数据,请稍后..."); startTmie = System.nanoTime(); gm.readDataNIO(f); totalTime = (System.nanoTime() - startTmie)/ 100000; System.out.println("readDataNIO(f) 读取数据成功, 耗时:" + totalTime); System.out.println(); System.out.println("正在读取数据,请稍后..."); startTmie = System.nanoTime(); gm.readDataMap_M(f); totalTime = (System.nanoTime() - startTmie)/ 100000; System.out.println("readDataMap_M(f) 读取数据成功, 耗时:" + totalTime); System.out.println(); System.out.println("正在读取数据,请稍后..."); startTmie = System.nanoTime(); gm.readDataMap(f); totalTime = (System.nanoTime() - startTmie)/ 100000; System.out.println("readDataMap 读取数据成功, 耗时:" + totalTime); System.out.println(); } catch (Exception e) { e.printStackTrace(); } if(bPrintData) { System.out.println("generator中生成的数据..."); int[][] intArr = generator.getDataArr(); for (int i = 0; i < count; i++) { for (int j = 0; j < size; j++) { System.out.printf("%1$3d", intArr[i][j]); } System.out.println(); } System.out.println("读取出来的数组..."); intArr = gm.getDataArr(); for (int i = 0; i < count; i++) { for (int j = 0; j < size; j++) { System.out.printf("%1$-5s", intArr[i][j]); } System.out.println(); } } } }
相关推荐
Java NIO(New IO)是Java平台上的新输入/输出流API,它提供了与传统IO(即Java IO)不同的数据处理方式。NIO在Java 1.4版本引入,并在后续版本中得到了进一步增强和完善。相较于传统的Java IO,NIO具有更高的性能和...
下面我们将深入探讨Java IO读取文件的技术及其在大数据场景下的应用。 1. **基础概念** - **流(Stream)**:Java IO基于流的概念,流是一组有序的数据序列,可以是字节流或字符流。数据从源(如文件)流向目的地...
Java NIO(New IO)是Java 1.4版本引入的一个新特性,它为Java提供了新的I/O操作方式,与传统的Java IO相比,NIO具有更高效、更灵活的特性,尤其是在处理大量并发I/O操作时。本篇将详细探讨Java NIO在写文件方面的...
Java NIO(New IO)是Java 1.4版本引入的一个新模块,它提供了一种新的方式来处理I/O操作,相比传统的IO流,NIO提供了更高效、更灵活的数据读写方式。在这个主题中,我们将深入探讨Java NIO如何用于写文件,特别是在...
3. **内存映射文件(Memory-Mapped Files)**:Java NIO提供了一个特殊的功能,即内存映射文件,它可以将文件直接映射到内存中,使得文件操作如同访问内存一样快速。对于大文件处理,内存映射文件是一种高效的策略,...
此外,NIO在某些特定情况下可能存在一些已知的问题,例如文件通道的内存映射操作可能会导致内存泄漏。 总的来说,Java NIO和IO各有优劣,开发者应根据实际需求来选择合适的模型。在需要处理大量并发连接,且对性能...
4. **内存映射文件**:NIO支持内存映射文件,直接将文件映射到内存,提高了大文件读写的性能。 **总结** 这个压缩包的示例代码可能包括了如何使用Java的IO和NIO API进行文件读写,以及如何利用`java.util.jar`包将...
3. **文件映射缓冲区**:对于大文件的处理,Java.nio提供了一个名为`MappedByteBuffer`的类,可以直接将文件映射到内存,避免了多次读写操作,极大地提高了效率。 4. **选择器(Selector)**:选择器允许程序同时...
NIO与传统的IO( Blocking IO)模型相比,最大的区别在于其非阻塞特性,使得一个线程可以同时处理多个连接请求,而无需为每个请求创建一个新的线程,从而避免了线程创建和销毁的开销,以及多线程同步的问题。...
Java NIO(New Input/Output)是Java标准库中提供的一种替代传统IO的高效I/O模型,它引入了通道(Channel)和缓冲区(Buffer)的概念,极大地优化了数据读写操作。在处理大流量实时业务系统时,NIO的优势尤为突出,...
与传统IO直接在流上读写不同,NIO需要先将数据存入Buffer,再从Buffer中读取或写入通道。 3. **选择器(Selectors)**:选择器允许单个线程监视多个通道的事件,如连接、读写等,大大提高了系统资源的利用率,尤其...
然而,NIO中的流与传统的IO流有所不同,它们不仅支持字节流,还支持字符流,并且引入了缓冲区(Buffer)的概念。缓冲区是NIO的核心,它允许我们批量处理数据,提高了效率。 接下来,我们来看NIO的另一重要概念——...
NIO的核心在于通道(Channels)和缓冲区(Buffers)的概念,它们与传统的流(Streams)模型不同,允许进行异步读写,从而提高了程序性能。 1. **通道(Channels)**:通道类似于流,但有以下几个关键区别: - 双向...
Java NIO(New IO)是Java 1.4版本引入的一个新API,全称为Non-blocking Input/Output,它提供了一种不同于传统IO的编程模型,传统IO基于块I/O,而NIO则基于通道(Channel)和缓冲区(Buffer)进行数据传输。NIO的...
此外,Java NIO的内存映射文件(MappedByteBuffer),允许文件或文件的一部分被映射到内存中,这使得对文件的访问和修改可以像访问内存一样简单快捷。 以上是Java NIO的核心概念和组件的介绍。在实际的编程实践中,...