我想测试是否可以锁定文件X.如果文件不存在或无法锁定,则失败。这听起来很简单,但我一直陷入死胡同。答案的一个捷径是提供一种获取FileChannel的方法,我可以进行独占锁定,而不会有创建文件的风险。让我解释一下......
如果没有可写的FileChannel,我就无法使用NIO lock()
,如果不打开文件X,我就无法获得可写的FileChannel,如果它不存在,则会创建它。我发现尝试将文件X打开为可写的每个Java方法都会创建它,如果它不存在,并且似乎没有办法将文件专门锁定在只读的FileChannel上。
即使检查确认文件存在也是有问题的。这是我的最新代码:
private LockStatus openAndLockFile(File file) {
if (Files.notExists(file.toPath())) {
synchronized (fileList) {
removeFile(file);
}
return LockStatus.FILE_NOT_FOUND;
}
try {
rwFile = new RandomAccessFile(file, "rw");
fileLock = rwFile.getChannel().lock();
}
catch ...
此代码的问题在于NotExists
代码运行时文件可能存在,但在new RandomAccessFile(file, "rw")
运行时消失。这是因为我在多个线程和多个进程中运行此代码,这意味着代码必须是气密的并且坚如磐石。
以下是我现有代码在两个进程中运行的问题示例:
1:进程A检测到新文件
2:进程B检测到相同的文件
3:进程A处理文件并将其移动到另一个文件夹
问题--->进程B意外创建一个空文件。 OOPS !!!
4:进程B检测到进程B创建的新文件,并处理它创建一个0字节的重复文件。
5:进程A还检测到进程B意外创建的新文件并尝试处理它......
这是一个使用C#的例子我想要做的事情:
Stream iStream = File.Open("c:\\software\\code.txt", FileMode.Open,
FileAccess.Read, FileShare.None)
非常感谢任何帮助或提示!谢谢!
答案 0 :(得分:1)
如果您试图阻止同一个应用程序(同一个JVM)中的两个线程处理同一个文件,那么您应该使用常规Java锁而不是文件锁来实现它。文件锁被授予JVM并且是可重入的...因此,如果一个线程“锁定”文件,另一个线程可以获取对同一文件的锁定。
我要做的是创建一个包装HashSet<File>
的线程安全锁定类,其中File
个对象表示存在的文件的绝对文件路径。然后通过锁定File
对象来实现“文件锁定”。
不幸的是,它们不仅会在不同的JVM中,而且有时会在不同的服务器上。
在这种情况下,最好的策略可能是使用数据库来实现锁定。