我有一个进程将经常被调用,从cron读取一个文件,其中包含某些与移动相关的命令。我的进程需要读取和写入这个数据文件,并保持它的锁定,以防止其他进程在这段时间内接触到它。一个完全独立的进程可以由用户执行,以便(潜在)写入/附加到这个数据文件。我希望这两个进程发挥良好,一次只能访问一个文件。
nio FileLock似乎是我所需要的(除了编写我自己的信号量类型文件),但我在读取时很难锁定它。我可以很好地锁和写,但是当尝试创建锁时,我会得到一个NonWritableChannelException。是否有可能锁定一个文件进行读取?RandomAccessFile似乎更接近我所需要的东西,但我不知道如何实现它。
下面是失败的代码:
FileInputStream fin = new FileInputStream(f);
FileLock fl = fin.getChannel().tryLock();
if(fl != null)
{
System.out.println("Locked File");
BufferedReader in = new BufferedReader(new InputStreamReader(fin));
System.out.println(in.readLine());
...异常将抛出在FileLock行上。
java.nio.channels.NonWritableChannelException
at sun.nio.ch.FileChannelImpl.tryLock(Unknown Source)
at java.nio.channels.FileChannel.tryLock(Unknown Source)
at Mover.run(Mover.java:74)
at java.lang.Thread.run(Unknown Source)看着JavaDocs,上面写着
当尝试写入原未打开的通道时引发的
未检查异常。
但我不一定要给它写信。当我尝试为编写目的创建一个FileOutpuStream等时,它很高兴,直到我尝试在同一个文件上打开一个FileInputStream。
发布于 2010-02-15 21:46:40
RandomAccessFile获取锁,然后打开FileInputStream。确保关闭两个!发布于 2010-05-29 12:38:02
如果您使用tryLock(0L, Long.MAX_VALUE, true)创建锁会更好。
这将创建一个共享锁,这对于阅读来说是正确的。
tryLock()是tryLock(0L, Long.MAX_VALUE, false)的缩写,即它请求独占的写锁。
发布于 2019-11-15 06:30:41
我编写了一个测试程序和bash命令来确认文件锁的有效性:
import java.io.File;
import java.io.RandomAccessFile;
import java.nio.channels.FileLock;
public class FileWriterTest
{
public static void main(String[] args) throws Exception
{
if (args.length != 4)
{
System.out.println("Usage: FileWriterTest <filename> <string> <sleep ms> <enable lock>");
System.exit(1);
}
String filename = args[0];
String data = args[1];
int sleep = Integer.parseInt(args[2]);
boolean enableLock = Boolean.parseBoolean(args[3]);
try (RandomAccessFile raFile = new RandomAccessFile(new File(filename), "rw"))
{
FileLock lock = null;
if (enableLock)
{
lock = raFile.getChannel().lock();
}
Thread.sleep(sleep);
raFile.seek(raFile.length());
System.out.println("writing " + data + " in a new line; current pointer = " + raFile.getFilePointer());
raFile.write((data+"\n").getBytes());
if (lock != null)
{
lock.release();
}
}
}
}使用bash命令运行以检查它是否工作:
for i in {1..1000}
do
java FileWriterTest test.txt $i 10 true &
done您应该只看到每10 be就会发生一次写入(从输出),并最终显示在文件中的所有数字。
输出:
/tmp wc -l test.txt
1000 test.txt
/tmp没有锁的相同测试显示数据丢失:
for i in {1..1000}
do
java FileWriterTest test.txt $i 10 false &
done输出:
/tmp wc -l test.txt
764 test.txt
/tmp应该很容易修改它来测试tryLock。
https://stackoverflow.com/questions/2268997
复制相似问题