Java 正在等待释放文件锁

Java 正在等待释放文件锁,java,io,fileutils,Java,Io,Fileutils,有一些Java问题与此类似,但没有一个问题接受了我能找到的答案,我的情况更具体一些。我有一个程序,在将文件送入目录时,一次处理一个文件。有时,这些文件可能会被程序锁定在使用中,在我的程序看到它们后,将其删除几秒钟。我无法控制那个项目。在我的程序中,当我的程序试图读取某个文件时,如果该文件正在使用,我已经有了错误处理来恢复。它会导致文件被完全跳过。我想要实现的是一个重试方案,以查看文件是否在几秒钟后解锁。在这里的另一个问题中,我发现了使用FileUtils.touch()的建议。这很方便,因为我已

有一些Java问题与此类似,但没有一个问题接受了我能找到的答案,我的情况更具体一些。我有一个程序,在将文件送入目录时,一次处理一个文件。有时,这些文件可能会被程序锁定在使用中,在我的程序看到它们后,将其删除几秒钟。我无法控制那个项目。在我的程序中,当我的程序试图读取某个文件时,如果该文件正在使用,我已经有了错误处理来恢复。它会导致文件被完全跳过。我想要实现的是一个重试方案,以查看文件是否在几秒钟后解锁。在这里的另一个问题中,我发现了使用
FileUtils.touch()
的建议。这很方便,因为我已经在我的项目中使用了FileUtils。根据javadoc,
FileUtils.touch()
,如果文件正被另一个进程使用,则抛出一个
IOException
。听起来很棒。然而,在我提到的答案下的一条评论没有任何解释地警告了比赛条件。以下是我正在考虑实施的代码:

// Implementing Sason's suggestion
int retries = 0;
while (retries < MAX_RETRIES) {
    try {
        processFile(file);
    } catch (IOException ioe) {
        // Assumes this is a file in use exception... bad thing?
        log.warn("File is in use.  Waiting 1 second to retry.");
        retries++;
        try {
            Thread.sleep(1000);
        } catch (InterruptedException ie) {
            log.warn("Thread interrupted while waiting for file lock to clear.");
            break;
        }
    }
}
//落实萨森的建议
int重试次数=0;
while(重试次数<最大重试次数){
试一试{
进程文件(文件);
}捕获(ioe异常ioe){
//假设这是一个正在使用的文件异常…不好吗?
log.warn(“文件正在使用,等待1秒重试”);
重试++;
试一试{
睡眠(1000);
}捕获(中断异常ie){
warn(“线程在等待文件锁清除时中断”);
打破
}
}
}
我意识到文件可能会在FileUtils.touch()和
processFile()
方法调用之间再次被锁定(我认为这是我找到的不可接受答案中警告的竞争条件),但这没关系。
processFile()
方法将像当前一样处理锁定错误。需要明确的是,在这种情况下,文件可以由另一个进程打开,但不能锁定

此外,虽然有时文件在一两秒钟后会解锁,但在某些情况下,删除文件的程序会无限期地保持锁定。我还需要避免无限次地尝试重新处理同一个文件,并且能够在重试次数用尽后无法处理文件时通知发件人


我是不是遗漏了什么?有更好/更安全的方法吗?

我会使用SchedueledExecutor服务提交工作,但会延迟一些时间,以尝试处理文件。如果处理失败,请反复发布工作,直到成功

这里需要FileUtils.touch吗?为什么不尝试读取文件,如果失败,请重试


睡眠的东西有点难看。如果处理多个文件,每个文件都必须使用自己的线程,直到完成为止。SchedueledExecutor服务将更加高效

这听起来不像
touch()
是测试文件是否打开的可靠方法。它可能在具有特定进程的特定系统上工作,并编写文件,这很好,但是如果在其他地方运行代码或更改编写器,则需要重新测试以确保它仍然工作。正确的方法是使用
文件锁
,但这需要编写程序使用底层文件系统锁机制。如果文件是在另一个进程中打开的,而该进程没有锁定该文件(例如,记事本++)。无法锁定它,因为
processFile()
将尝试锁定该文件。我确实明白你关于
FileLock
的观点,但你是对的,它需要进行大量重构。我确实认为
touch()
可以跨平台工作,但同样需要注意的是,另一个程序可能打开了文件,但没有锁定。我同意。竞争是因为检查和操作之间没有原子性。如果操作因无法获取锁而失败,则没有问题。稍后再试。这是一个有趣的想法,我曾经考虑过,但最初拒绝了,因为有时候文件会无限期地被锁定,程序会在无法处理的文件上循环。在错误处理中,将向发送方提供一个通知,告知无法处理该文件,并将该文件添加到忽略列表中。一天结束时,无法处理的文件列表将发送给发件人。我真的不想改变这种行为,我只想在文件进入未处理列表之前留出几秒钟的时间让其可用。此外,我同意Thread.sleep()的做法有点难看,但文件确实需要同步处理,因此如果它阻止下一个要处理的文件,也没关系。我几乎希望我不必按顺序处理文件(尽可能接近到达顺序)。这实际上会使事情简化很多,因为我可以完全按照您所说的做,并在一定次数的重试后使runnable本身过期。我甚至可以用“未来”来代替。好吧,遗嘱执行人不会阻止你计算重试次数并停止重试。另一件事是忽略中断的异常并继续循环。你破坏了应用程序及时关闭的能力。关于InterruptedException,你是对的,谢谢你指出这一点。我想我遗漏了遗嘱执行人的一些信息。注释太长,但是如果我一次处理10个文件,并且第一个文件被锁定,runnable需要在内部重试该文件,或者在内部跟踪该文件,以便下次执行时知道它正在尝试第二次、第三次等。这似乎会让人更加困惑。这真的比我做的好吗?我一定错过了什么