在Windows上用Java编写并发文件

时间:2009-04-03 11:25:52

标签: java file-io portability concurrency

当您在同一个文件上同时打开两个(或更多)FileOutputStream时会发生什么?

Java API说:

  

某些平台特别允许一次只打开一个FileOutputStream(或其他文件写入对象)来写文件。

我猜Windows不是这样的平台,因为我有两个线程读取一些大文件(每个都是不同的文件),然后将其写入同一个输出文件。抛出没有异常,文件被创建并且似乎包含来自两个输入文件的块。

附带问题:

  • 这对Unix也是如此吗?
  • 由于我希望行为相同(实际上我希望一个线程正确编写而另一个线程要警告冲突),我如何确定文件已经打开进行写入?

4 个答案:

答案 0 :(得分:16)

当文件有另一个文件时,没有一种可靠的,跨平台的方式被动通知 - 即,如果文件已经打开进行写入,则引发异常。但是,有几种技术可以帮助您主动检查。

如果多个进程(可以是Java和非Java的混合)可能正在使用该文件,请使用FileLock。成功使用文件锁的关键是要记住它们只是“建议性的”。如果您检查锁定,则保证锁定可见,但如果您忘记,它将不会阻止您对文件执行操作。访问该文件的所有进程都应设计为使用锁定协议。

如果单个Java进程正在使用该文件,您可以使用Java内置的并发工具来安全地执行此操作。您需要一个可查看所有线程的映射,该映射将每个文件名与其对应的锁实例相关联。可以使用File个对象或a related question对文件轻松调整canonical paths的答案。锁定对象可以是FileOutputStream,流周围的一些包装,或ReentrantReadWriteLock.

答案 1 :(得分:4)

我会谨慎地让操作系统为您确定文件状态(因为这取决于操作系统)。如果您有共享资源,我会使用Re-entrant lock

限制对其的访问

使用此锁意味着一个线程可以获取资源(文件)并写入它。下一个线程可以检查另一个线程持有的锁,和/或无限期阻塞,直到第一个线程释放它。

Windows(我认为)会限制写入同一文件的两个进程。我不相信Unix也会这样做。

答案 2 :(得分:1)

如果你所谈论的2个线程在同一个JVM中,那么你可以在两个线程都可以访问的某个地方有一个布尔变量。

答案 3 :(得分:1)

Unix允许并发写入者使用同一个文件。

您不应尝试多次写入同一文件。如果你有设计缺陷。