用于*读取*文件的java FileDescriptor .sync()的逆转

时间:2009-06-18 14:23:14

标签: java multithreading file-io concurrency

在FileDesciptor的.sync()方法中读取javadoc,很明显,sync()主要涉及将任何修改的缓冲区提交回底层存储。即,确保您的程序具有输出的任何内容实际上将它带到磁盘(或套接字或有什么用户,但我的问题主要与磁盘有关)。

但是另一个方向呢,INPUT怎么样?假设我的程序在内存中缓存了java.io.RandomAccessFile的某些部分,我想读取文件的那些部分,但是自上次程序读取这些块以来,可能还有其他一些进程修改了文件的那些部分?

这类似于在C程序中将变量标记为“volatile”;其他东西可能改变了你只是方便副本的“真实版本”。

即,你怎么能确定你的java程序读取的内容至少是合理的最新版本?

(显然,'最新'的定义很重要。纯粹作为一个例子,假设另一个进程,写入文件的进程,可能每秒执行一次,并假设读取进程可能每分钟读取一次。在这种情况下,性能并不是什么大问题,只需要确保读取器读取的内容与写入内容的内容一致,即一秒钟内。)< / p>

3 个答案:

答案 0 :(得分:2)

在重新读取文件之前,通常最好使用File.lastModified()检查文件的上次修改时间戳。如果此时间戳不比上次读取文件时更新,则无需更多磁盘I / O来重新读取您感兴趣的块。但要注意的一点是,如果您使用的是网络文件系统,则在更新内容时,可能无法始终立即更新上次修改的时间戳。如果您正在处理更新文件的本地进程和运行代码读取文件的另一个本地进程,则很可能不会遇到此问题。

我过去成功的一种方法是让一个单独的线程在某个时间间隔(例如5秒)轮询该文件以获取最后修改的时间戳。如果文件已更改,请重新处理该文件并将事件发送给已注册的侦听器。就我而言,5秒钟就足以获得更新。

答案 1 :(得分:1)

在将文件读入内部缓冲区的那一刻,内容与磁盘上的内容保持同步。

如果您想确保在下次访问时获得最新内容,则还必须再次转到磁盘,跳过所有内部缓冲区和缓存。如果你真的想确定,所有这些图层都被跳过,你将不得不从头开始重新打开文件并寻找你想要访问的相应位置。

当然,如果您在每次可能访问数据时访问磁盘,那么您的性能将会下降。不要认为3-5倍左右,而是数量级。

答案 2 :(得分:0)

如果您控制的另一个程序是唯一一个写入该文件的程序,那么最好在同一个Java进程坐标中有2个线程。最简单的解决方案是创建java.util.concurrrent.atomic.AtomicBoolean。作者线程在set(true)上调用AtomicBoolean,并且读者调用getAndSet(false)。如果getAndSet()返回true,那么您就知道读者需要重新读取数据。如果这是一个问题,你可以同步一些对象,以防止作者在读者阅读时写作。

你在问题​​中说“过程”,所以也许你担心系统改变数据的任何其他过程。在这种情况下,我认为最好的办法就是重新打开并重新读取数据。如果你真的每分钟只阅读一次,那么这对性能的影响应该可以忽略不计。