如何使用Java锁定文件(如果可能)

时间:2020-03-06 14:40:19  来源:igfitidea点击:

我有一个使用FileReader打开文件的Java进程。如何防止另一个(Java)进程打开该文件,或者至少通知第二个进程该文件已打开?如果文件已打开(这解决了我的问题),这是否使第二个进程自动获得异常?还是我必须在第一个进程中使用某种标记或者参数显式打开该文件?

澄清:

我有一个Java应用程序,其中列出了一个文件夹并打开列表中的每个文件进行处理。它依次处理每个文件。每个文件的处理包括读取文件并根据内容进行一些计算,大约需要2分钟。我也有另一个Java应用程序,它执行相同的操作,但写在文件上。我想要的是能够同时运行这些应用程序,这样情况就可以这样。 ReadApp列出文件夹并找到文件A,B,C。它将打开文件A并开始读取。 WriteApp列出该文件夹并查找文件A,B,C。它将打开文件A,看到已打开(通过异常或者其他方式),然后转到文件B。ReadApp完成了文件A并继续到B。打开并继续到C。至关重要的是,在ReadApp读取同一文件时,WriteApp不要写,反之亦然。它们是不同的过程。

解决方案

如果我们可以使用Java NIO(JDK 1.4或者更高版本),那么我认为我们正在寻找的是java.nio.channels.FileChannel.lock()。

FileChannel.lock()

结合使用java.nio.channels.FileLock和java.nio.channels.FileChannel

我们使用java.nio。* API锁定文件。但是,这不能保证锁定,这取决于基础操作系统是否支持锁定。据我了解,像Linux这样的操作系统不支持锁定,因此即使使用这些API也无法锁定

FileChannel.lock可能就是我们想要的。

FileInputStream in = new FileInputStream(file);
try {
    java.nio.channels.FileLock lock = in.getChannel().lock();
    try {
        Reader reader = new InputStreamReader(in, charset);
        ...
    } finally {
        lock.release();
    }
} finally {
    in.close();
}

(免责声明:代码未编译,并且未经测试。)

请注意FileLock的API文档中标题为"平台依赖项"的部分。

使用RandomAccessFile,获取它的频道,然后调用lock()。输入或者输出流提供的通道没有足够的特权来正确锁定。确保在finally块中调用unlock()(关闭文件并不一定会释放锁)。

这可能不是我们想要的,但是为了从另一个角度解决问题……。

这两个Java进程可能想要访问同一应用程序中的同一文件吗?也许我们可以通过一个同步的方法(或者,甚至使用JSR-166更好)来过滤对文件的所有访问?这样,我们可以控制对文件的访问,甚至可以控制队列访问请求。