Java--Stream,NIO ByteBuffer,NIO MappedByteBuffer性能对比

Posted 11楼的日记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java--Stream,NIO ByteBuffer,NIO MappedByteBuffer性能对比相关的知识,希望对你有一定的参考价值。

目前Java中最IO有多种文件读取的方法,本文章对比Stream,NIO ByteBuffer,NIO MappedByteBuffer的性能,让我们知道到底怎么能写出性能高的文件读取代码。

 

package com.seeyon.nio;

import org.junit.Test;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;

/**
 * Created by yangyu on 16/12/28.
 */

/**
 * 比较Stream流,NIO ByteBuffer,NIO MappedByteBuffer性能对比
 * 其中Stream最慢,NIO MappedByteBuffer最快
 * Stream:1000ms
 * NIO ByteBuffer:220ms
 * NIO MappedByteBuffer:112ms
 */
public class Compare {

    /**
     * 使用stream作为IO流读取和写入文件
     * 速度:1000ms左右
     *
     * @throws IOException
     */
    @Test
    public void useStream() throws IOException {

        long startTime = System.currentTimeMillis();
        /**
         * 4000000个整数长度的文件
         */
        int num = 2000 * 2000;

        /**
         * 带缓冲的输出流,写文件
         */
        DataOutputStream dataOutputStream = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("/Users/yangyu/Downloads/compare.tmp")));
        for (int i = 0; i < num; i++) {
            dataOutputStream.writeInt(i);
        }
        dataOutputStream.close();

        int data = 0;
        /**
         * 带缓冲的输入流,读文件
         */
        DataInputStream in = new DataInputStream(new BufferedInputStream(new FileInputStream("/Users/yangyu/Downloads/compare.tmp")));
        try {
            while (true) {
                data = in.readInt();
            }
        } catch (EOFException e) {
            System.out.println("读取完成"+data);
        }
        in.close();
        long endTime = System.currentTimeMillis();
        System.out.println("ms:" + (endTime - startTime));
    }

    /**
     * 使用NIO ByteBuffer
     * 时间:220ms
     * @throws IOException
     */
    @Test
    public void useNioByteBuffer() throws IOException {
        long startTime = System.currentTimeMillis();
        int num = 2000*2000;
        /**
         * 文件输出流
         */
        FileOutputStream fileOutputStream = new FileOutputStream("/Users/yangyu/Downloads/compare.tmp");
        /**
         * NIO Channel 通道
         */
        FileChannel fileChannel = fileOutputStream.getChannel();
        /**
         * ByteBuffer缓冲区
         */
        ByteBuffer buffer = ByteBuffer.allocate(num*5);
        for (int i = 0; i < num; i++) {
            buffer.putInt(i);
        }
        /**
         * 为写做准备
         */
        buffer.flip();
        /**
         * 写操作
         */
        fileChannel.write(buffer);
        fileChannel.close();

        /**
         * 缓冲区
         */
        ByteBuffer buffer1 = ByteBuffer.allocate(num*5);
        /**
         * 文件输入流
         */
        FileInputStream in = new FileInputStream("/Users/yangyu/Downloads/compare.tmp");
        /**
         * 输入通道
         */
        FileChannel fin = in.getChannel();
        /**
         * 为读取做准备
         */
        buffer1.clear();
        System.out.println(buffer1.limit());
        /**
         * 读取
         */
        fin.read(buffer1);
        fin.close();

        long endTime = System.currentTimeMillis();
        System.out.println("ms:" + (endTime - startTime));
        buffer1.flip();
        System.out.println(buffer1.limit());
    }

    /**
     * 使用MappedByteBuffer,通过FileChannel将文件映射到内存
     * 时间:112ms
     * @throws IOException
     */
    @Test
    public void useRandomAccess() throws IOException {
        long startTime = System.currentTimeMillis();
        int num = 2000*2000;

        /**
         * 使用可随机访问位置的RandomAccessFile
         */
        RandomAccessFile file = new RandomAccessFile("/Users/yangyu/Downloads/compare.tmp","rw");
        /**
         * 获取通道Channel
         */
        FileChannel fileChannel = file.getChannel();
        /**
         * 将文件映射到缓冲区MappedByteBuffer
         */
        MappedByteBuffer mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE,0,num*4);
        /**
         * 写文件
         */
        for (int i = 0; i < num; i++) {
            mappedByteBuffer.putInt(i);
        }
        fileChannel.close();

        int data=0;
        RandomAccessFile file1 = new RandomAccessFile("/Users/yangyu/Downloads/compare.tmp","rw");
        FileChannel fc = file1.getChannel();
        MappedByteBuffer mappedByteBuffer1 = fc.map(FileChannel.MapMode.READ_WRITE,0,file1.length());
        /**
         * 读文件
         */
        while (mappedByteBuffer1.hasRemaining()){
            data = mappedByteBuffer1.getInt();
        }
        fc.close();
        long endTime = System.currentTimeMillis();
        System.out.println("ms:" + (endTime - startTime));
        System.out.println(data);
    }
}

 

结论非常明显啦,以后再使用IO读写文件的时候,多使用NIO MappedByteBuffer吧,毕竟NIO比老IO性能好太多啦。

以上是关于Java--Stream,NIO ByteBuffer,NIO MappedByteBuffer性能对比的主要内容,如果未能解决你的问题,请参考以下文章

java 读取一个巨大的文本文件,该如何实现 既能保证内存不溢出 又能保证性能 ?

java bytebuffer slice 没有按照文档工作

java stream 及早求值

Java Stream 的技巧

Java8——Stream流

Java Stream