代码之家  ›  专栏  ›  技术社区  ›  JustJeff

用于读取*文件的JavaFieldSudio.ScCo()的逆

  •  2
  • JustJeff  · 技术社区  · 17 年前

    在读取filedesciptor的.sync()方法上的javadoc时,很明显,sync()主要关注将任何修改过的缓冲区提交回底层存储。也就是说,确保你的程序有 输出 实际上会把它放在磁盘上(或插座上,或者你有什么,但我的问题主要是关于磁盘)。

    但是另一个方向呢,输入呢?假设我的程序在内存中缓存了java.io.randomaccessfile的某些部分,我想读取该文件的这些部分,但也许自从我的程序上次读取这些块以来,其他进程已经修改了该文件的这些部分?

    这类似于在C程序中将一个变量标记为“volatile”;其他一些东西可能已经改变了某个东西的“真实版本”,而您只需要一个方便的副本。

    也就是说,如何确定Java程序的读数至少是最新的?

    (明确“最新”事项的定义。纯粹作为一个例子,假设另一个进程,即写入文件的进程,以每秒可能一次的顺序执行此操作,并且假设读取进程可能每分钟读取一次。在这种情况下,性能不是什么大问题,只是要确保读者读到的内容与写下的内容一致,比如说,一秒钟之内。)

    3 回复  |  直到 17 年前
        1
  •  2
  •   Gary    17 年前

    在重新读取文件之前,最好使用file.last modified()检查文件的上次修改时间戳。如果这个时间戳不比您上次读取文件的时间更新,您不需要费心更多的磁盘I/O来重新读取您感兴趣的块。不过要记住的一点是,如果您使用网络文件系统,那么在更新内容时,最后修改的时间戳可能不会立即更新。如果您处理的是更新文件的本地进程和运行代码读取文件的另一个本地进程,则很可能不会遇到此问题。

    我过去成功使用的一种方法是让一个单独的线程在特定的时间间隔(比如5秒)上轮询文件,以获取最后修改的时间戳。如果文件已更改,请重新处理该文件并向注册的侦听器发送事件。在我的例子中,5秒比很快就能得到更新。

        2
  •  1
  •   Kosi2801    17 年前

    当文件被读取到内部缓冲区时,内容与磁盘上的内容是最新的。

    如果要确保在下次访问时具有最新内容,还必须再次转到磁盘,跳过所有内部缓冲区和缓存。如果您真的想确定,所有这些层都被跳过,那么您必须从头重新打开文件,并按照您想要访问的位置进行搜索。

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

        3
  •  0
  •   AngerClown    17 年前

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

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