Java Files.newInputStream创建慢速InputStream

Java Files.newInputStream创建慢速InputStream,java,Java,在我的Windows 7文件中,newInputStream返回sun.nio.ch.ChannelInputStream。当我对比FileInputStream测试它的性能时,我惊讶地发现FileInputStream更快 这个测试 InputStream in = new FileInputStream("test"); long t0 = System.currentTimeMillis(); byte[] a = new byte[16 * 1024];

在我的Windows 7文件中,newInputStream返回sun.nio.ch.ChannelInputStream。当我对比FileInputStream测试它的性能时,我惊讶地发现FileInputStream更快

这个测试

    InputStream in = new FileInputStream("test");
    long t0 = System.currentTimeMillis();
    byte[] a = new byte[16 * 1024];
    for (int n; (n = in.read(a)) != -1;) {
    }
    System.out.println(System.currentTimeMillis() - t0);
在125毫秒内读取100mb文件。如果我将第一行替换为

InputStream in = Files.newInputStream(Paths.get("test"));
我得到320毫秒


如果Files.newInputStream速度较慢,那么它与FileInputStream相比有哪些优势?

我不想成为buzzkill,但javadoc没有说明任何优势,也没有说明我能找到的任何文档

打开一个文件,返回要从该文件读取的输入流最新版本 流不会被缓冲,并且不需要支持标记 或重置方法多个用户可以安全访问该流 并发线程。读取从文件开头开始。 返回的流是否可异步关闭和/或 可中断性是高度特定于文件系统提供程序的,因此 未指定


我认为该方法只是一种实用方法,不一定要取代或改进
FileInputStream
。请注意,并发点可能解释了某些速度减慢的原因。

如果您第二次测试了
新文件输入流,您可能只是看到了操作系统对缓存启动的影响。Java对I/O绑定的进程造成任何重大差异是不合理的。用另一种方法,在更大的数据集上进行测试。

文件中说

“流将不会被缓冲”

这是因为Files.newInputStream(路径)支持非阻塞IO

您可以在调试模式下尝试,可以打开非阻塞inputstream,同时修改文件,但如果使用FileInputStream,则无法执行此类操作

FileInputStream将需要文件的“写锁”,因此它可以缓冲文件的内容,提高读取速度

但是ChannelInputStream不能。必须保证它正在读取文件的“当前”内容


以上是我的经验,我没有检查Java文档中的每一点。

您的
FileInputStream
FileOutputstreams
可能会引入较长的GC暂停

每次创建
文件输入流
文件输出流
时,您都在创建一个对象。即使您正确且及时地关闭它,它也将被放入一个特殊类别,只有在垃圾收集器执行完整GC时才会被清理。遗憾的是,由于向后兼容性的限制,这并不是JDK中任何时候都可以解决的问题,因为可能存在一些代码,其中有人扩展了
FileInputStream/FileOutputStream
,并且依赖这些
finalize()
方法来确保调用
close()

解决方案(至少如果您使用的是Java7或更高版本)并不太难 -只需切换到
文件.newInputStream(…)
文件.newOutputStream(…)


100MB远不足以运行系统。在后台运行的任何东西都可能很容易干扰I/O。请使用大约100倍的数据(10GB)进行尝试,但不要在后台运行任何东西,以获得有意义的数字。那些阻止文件通道适配器的开销非常大。我想直接使用FileChannel是可以的,但这可以解决…(并不是说您的基准测试是有效的:)API并没有说FileInputStream不是线程安全的。请注意,FileInputStream使用volatile字段和ThreadLocal internallyJava输入流不支持非阻塞I/O,;没有通过任何方式对Java中的文件进行非阻塞I/O;即使有,也不能解释速度差
FileInputStream
也没有缓冲,并且不需要写锁。您似乎混淆了锁定和阻塞模式,以及两者与缓冲。它们是三种不同的东西,它们不会相互影响。你的答案没有道理。不需要缓冲区(在给定的基准测试中),因为读取的大小是16k(无论如何都不会使用缓冲区)。除此之外,不存在读写锁这类东西。出于GC原因,SpotBugs报告了这一点。