这看起来并不简单,特别是对于读/写缓冲的FileChannel。是否有任何开源实现的地方,我可以基于我的实现?
要清楚那些不理解的人:
FileChannel在操作系统级别进行缓存,我想在Java级别进行缓冲。请阅读此处以了解:FileChannel#force and buffering
@Peter我想从快速消息流中将大文件写入磁盘。缓冲和批处理是要走的路。所以我想在Java中批处理,然后调用FileChannel.write。
答案 0 :(得分:3)
FileChannel仅适用于ByteBuffers,因此它是自然缓冲的。如果你需要额外的缓冲来将数据从ByteBuffer复制到ByteBuffer,但我不确定你为什么要这样做。
FileChannel在操作系统级别执行任务
FileChannel会告诉操作系统该做什么。操作系统通常有一个磁盘缓存,但FileChannel不知道是否是这种情况。
我想在Java级别进行缓冲
你很幸运,因为你没有选择。 ;)这是唯一的选择。
答案 1 :(得分:3)
我建议使用BufferedOutputStream
包裹FileOutputStream
。我不相信你会通过与ByteBuffer
和FileChannel
混淆看到任何的性能改进,并且如果你要留下很多难以维护的代码,你走那条路。
推理非常简单:无论采用何种方法,所涉及的步骤都是相同的:
ByteBuffer
中移动缓冲的字节或缓冲区(是的,您需要直接缓冲区),您仍然在移动字节。您将使用ByteBuffer
进行更多JNI调用,但这是一个边际成本。fwrite
,一个内核调用,将C堆中的字节复制到内核维护的磁盘缓冲区中。根据您实现这些步骤的确切方式,可能会有几微秒的增加或丢失,但您无法更改基本步骤。
FileChannel
确实为您提供了调用force()
的选项,以确保第5步实际发生。这可能实际上降低您的整体性能,因为在写入字节之前,基础fsync
调用不会返回。如果你真的想这样做,你总是可以从底层流中获取频道。
结论:我愿意打赌你实际上已经受到了IO限制,并且除了更好的硬件之外没有办法解决这个问题。
答案 2 :(得分:-1)
我有两个线程,生产者线程生成ByteBuffers并将它们附加到队列的尾部,消费者线程每次从队列的头部删除一些ByteBuffers,并调用fileChannel.write(ByteBuffer [])。 / p>