首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于读写的Java FileLock

用于读写的Java FileLock
EN

Stack Overflow用户
提问于 2010-02-15 21:20:22
回答 3查看 39.1K关注 0票数 23

我有一个进程将经常被调用,从cron读取一个文件,其中包含某些与移动相关的命令。我的进程需要读取和写入这个数据文件,并保持它的锁定,以防止其他进程在这段时间内接触到它。一个完全独立的进程可以由用户执行,以便(潜在)写入/附加到这个数据文件。我希望这两个进程发挥良好,一次只能访问一个文件。

nio FileLock似乎是我所需要的(除了编写我自己的信号量类型文件),但我在读取时很难锁定它。我可以很好地锁和写,但是当尝试创建锁时,我会得到一个NonWritableChannelException。是否有可能锁定一个文件进行读取?RandomAccessFile似乎更接近我所需要的东西,但我不知道如何实现它。

下面是失败的代码:

代码语言:javascript
复制
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行上。

代码语言:javascript
复制
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。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-02-15 21:46:40

  1. 您是否知道,锁定文件不会阻止其他进程接触它,除非它们也使用锁?
  2. ,您必须通过可写通道锁定它。在"rw“模式下通过RandomAccessFile获取锁,然后打开FileInputStream。确保关闭两个!
票数 20
EN

Stack Overflow用户

发布于 2010-05-29 12:38:02

如果您使用tryLock(0L, Long.MAX_VALUE, true)创建锁会更好。

这将创建一个共享锁,这对于阅读来说是正确的。

tryLock()tryLock(0L, Long.MAX_VALUE, false)的缩写,即它请求独占的写锁。

票数 13
EN

Stack Overflow用户

发布于 2019-11-15 06:30:41

我编写了一个测试程序和bash命令来确认文件锁的有效性:

代码语言:javascript
复制
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命令运行以检查它是否工作:

代码语言:javascript
复制
for i in {1..1000}
do
java FileWriterTest test.txt $i 10 true &
done

您应该只看到每10 be就会发生一次写入(从输出),并最终显示在文件中的所有数字。

输出:

代码语言:javascript
复制
/tmp wc -l test.txt
1000 test.txt
/tmp

没有锁的相同测试显示数据丢失:

代码语言:javascript
复制
for i in {1..1000}
do
java FileWriterTest test.txt $i 10 false &
done

输出:

代码语言:javascript
复制
/tmp wc -l test.txt
764 test.txt
/tmp

应该很容易修改它来测试tryLock。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2268997

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档