简单来说:使用sqlitejdbc作为后端的swing应用程序。目前,启动使用相同数据库文件的多个实例没有问题。应该有。 该文件已被锁定(在应用程序运行时无法将其删除)因此检查应该是微不足道的。原来没有。
File f = new File("/path/to/file/db.sqlite");
FileChannel channel = new RandomAccessFile(f, "rw").getChannel();
System.out.println(channel.isOpen());
System.out.println(channel.tryLock());
结果
true
sun.nio.ch.FileLockImpl[0:9223372036854775807 exclusive valid]
无论应用程序是否正在运行。我错过了这一点吗? TIA。
答案 0 :(得分:2)
FileLocks是JVM独有的,而不是单个线程。因此,如果您在与Swing应用程序相同的进程中运行该代码,您将获得锁定,因为它由JVM共享。
如果您的Swing应用程序没有运行,则没有其他进程争夺锁定,因此您可以很好地获取它。
答案 1 :(得分:2)
文件系统级别锁定与其他应用程序交互。你从FileChannel得到其中一个。因此,在示例代码中执行的操作将使文件看起来锁定到另一个进程,例如vi。
但是,JVM中的其他Java线程或进程将看不到锁。关键句是“代表整个Java虚拟机保存文件锁。它们不适合控制同一虚拟机中多个线程对文件的访问。”你没有看到锁定,因此您在与应用程序相同的JVM中运行sqlitejdbc。
所以问题是你如何看待你的JVM是否已经获得了对文件的锁定(假设你没有控制获取锁的代码)?我有一个建议是尝试获取文件的不同子集的独占锁,例如使用以下代码:
fc.tryLock(0L, 1L, false)
如果已经存在锁定,则应该获得OverlappingFileLockException。这有点hacky但可能有用。
答案 2 :(得分:0)
public class Main {
public static void main(String [] args) throws Exception {
File f = new File("/path/to/file/db.sqlite");
FileChannel channel = new RandomAccessFile(f, "rw").getChannel();
System.out.println(channel.isOpen());
System.out.println(channel.tryLock());
Thread.sleep(60000);
}
}
如果这没有锁定,则您知道tryLock()无法在您的OS /驱动器/ JVM上运行。如果这确实锁定了,那么你的逻辑就会出现其他问题。请在评论中告诉我们结果。