在 java 中缓冲缓冲流的结果是什么



正在为以下人员编写javadoc:

/**
 * ...Buffers the input stream so do not pass in a BufferedInputStream ...
 */
public static void meth(InputStream is) throws IOException {
    BufferedInputStream bis = new BufferedInputStream(is,
            INPUT_STREAM_BUFFER_SIZE);
    // rest omitted
}

但是,将缓冲输入流传入真的有问题吗?所以这个:

InputStream is = new BufferedInputStream(new FileInputStream("C:/file"), SIZE);
meth(is);

会将is缓冲到bis中 - 或者 Java 会检测到is已经缓冲并设置bis = is?如果是,不同的缓冲区大小会有所不同吗?如果没有,为什么不呢?
注意:我说的是输入流,但实际上这个问题对输出流也有效

但是,将缓冲输入流传入真的有问题吗?

没有。 这样做可能会产生很小的开销,但与读取输入的总体成本相比,它可以忽略不计。

如果你看一下BufferedInputStream的代码,(例如read1方法(,你会看到块读取在缓冲流堆叠时是高效的。

[重新示例代码:] java 会检测到已经缓冲并设置bis = is吗?

不。

如果没有,为什么不呢?

因为Java(语言,编译器(通常不理解Java库类的语义。 在这种情况下,由于这种优化的好处可以忽略不计,因此我不值得实施。

当然,您可以自由编写meth方法来显式执行此类操作...虽然我预测这不会有什么区别。


我不太明白为什么在 read1 中,只有在请求的长度小于 buf.length 时才"费心"复制到输入缓冲区(或者如果输入流中有标记的位置(

我假设您指的是这段代码(read1(:

    if (len >= getBufIfOpen().length && markpos < 0) {
        return getInIfOpen().read(b, off, len);
    }

第一部分是说,如果用户请求的缓冲区大小小于流配置的缓冲区大小,我们不希望使缓冲短路。 (否则,我们会遇到一个问题,即使用较小的请求长度进行read(byte[], int, int)将是悲观的。

第二部分与标记/重置的实现方式有关。 BufferedInputStream不是在基础流上使用标记/重置(可能支持也可能不支持(,而是使用缓冲区来实现它。 你所看到的是这个逻辑的一部分。 (您可以自己处理细节...阅读源代码中的注释。

如果缓冲流两次,那么它将使用更多的内存,并且比只缓冲一次时速度慢,但它仍然可以工作。

当然值得记录您的流执行缓冲,以便用户知道他们不需要自己这样做。

一般来说,最好劝阻而不是积极防止这种滥用。

答案是否定的,Java不会检测到双重缓冲。

由用户来避免此问题。BufferedInputStream无法知道传入构造函数的InputStream是否被缓冲。

下面是 BufferedInputStream 构造函数的源代码:

public BufferedInputStream(InputStream in, int size) {
    super(in);
    if (size <= 0) {
        throw new IllegalArgumentException("Buffer size <= 0");
    }
    buf = new byte[size];
}

编辑

从评论中,双重缓冲流有问题吗?

简短的回答是肯定的

缓冲的想法是提高速度,以便将数据假脱机到内存中并以块的形式写出(通常写到非常慢的IO(。如果双重缓冲,则会将数据假脱机到内存中,然后将该数据刷新回内存中的其他位置。这在速度方面肯定是有代价的......

最新更新