为什么FileInputStream比具有相同缓冲区大小的BufferedInputStream快得多

问题描述 投票:-1回答:1

这是两段代码,如下所示:

FileInputStream is = new FileInputStream(tmp);
byte[] buf = new byte[1024];
while (is.read(buf) > -1) {
}

BufferedInputStream is = new BufferedInputStream(new FileInputStream(tmp),1024);
while (is.read() > -1) {
}

BufferedInputStream源代码看来,它们将花费相同的时间,但实际上第一种方式运行得更快(在200M文件上166ms对5159ms)。为什么?

java bufferedinputstream
1个回答
0
投票

FileInputStream#read(byte b[])将在每次调用时将多个字节读入b。在这种情况下1024

BufferedInputStream#read()每次调用都会读取一个字节。在内部BufferedInputStream将使用大小为1024的缓冲区来复制它所包含的流中的数据,但是,您仍然执行的操作远远超过您所需的操作。

尝试使用BufferedInputStream#read(byte b[])方法,您会注意到与FileInputStream相当的速度。

同样如OldCurmudgeon所述,BufferedInputStream#read方法是同步的:

public synchronized int read() throws IOException {
    if (pos >= count) {
        fill();
        if (pos >= count)
            return -1;
    }
    return getBufIfOpen()[pos++] & 0xff;
}

为了向您展示这可能带来多少开销的示例,我做了一个小型演示:

public class Main {
    static final double TEST_SIZE = 100000000.0;
    static final double BILLION = 1000000000.0;

    public static void main(String[] args) {
        testStandard();
        testSync();
    }

    static void testStandard() {
        long startTime = System.nanoTime();
        for (int i =0; i < TEST_SIZE; i++) {
        }
        long endTime = System.nanoTime();
        System.out.println((endTime - startTime)/ BILLION  + " seconds");
    }

    static void testSync() {
        long startTime = System.nanoTime();
        for (int i =0; i < TEST_SIZE; i++) {
            synchronized (Main.class) {}
        }
        long endTime = System.nanoTime();
        System.out.println((endTime - startTime)/ BILLION  + " seconds");
    }
}

在我的计算机上,同步调用的执行时间大约长达40倍:

0.13086644 seconds
4.90248797 seconds
© www.soinside.com 2019 - 2024. All rights reserved.