我编写了一个小工具,我希望它能维持单例运行,为此我在程序开头设置了 FileLock 独占锁,在IDE里面测试一切正常!但是当我把它导出jar文件,并打包成exe应用程序后,出现了奇怪的现象,FileLock 似乎失效了!具体表现为:我打开一个这个程序后,啥也不做,直接打开第二个,FileLock 工作正常!但是,当我打开一个这个程序后,点击了上面的运行按钮(按钮内部会创建并启动一个线程,用来执行一些耗时任务,没有执行释放 FileLock 锁的代码!)之后,在不关闭当前程序的情况下,接着打开第二个这个程序,他居然可以成功启动!FileLock 似乎失效了!这是怎么回事?
【以下回答由 GPT 生成】
这个问题可能是因为文件锁的作用范围只在同一个进程内有效,而当将程序打包成jar文件并作为单独的应用程序运行时,每次启动都会创建一个新的进程,导致文件锁无法起到限制进程数量的作用。
解决这个问题的一种方法是使用一个唯一的标识来判断是否已经有一个实例在运行。可以创建一个文件,用来记录某个标识是否存在。当启动程序时,先检查该文件是否存在,如果已经存在,则说明已经有一个实例在运行,直接退出程序;如果不存在,则创建该文件,并在程序结束时删除该文件。
以下是一个示例代码,展示如何使用文件来判断程序是否已经在运行:
import java.io.File;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.file.StandardOpenOption;
public class SingletonApp {
private static final String LOCK_FILE_PATH = "path/to/lock/file";
public static void main(String[] args) {
File lockFile = new File(LOCK_FILE_PATH);
try {
if (lockFile.createNewFile()) {
// 文件不存在,说明没有实例在运行,可以继续执行
System.out.println("程序开始运行");
// 注册程序结束时的钩子函数,用于删除锁文件
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
lockFile.delete();
System.out.println("程序结束运行");
}));
// 在这里执行你的代码逻辑
// ...
} else {
// 文件已存在,说明已经有一个实例在运行,直接退出程序
System.out.println("已有实例在运行,程序退出");
System.exit(0);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
这样,当运行该程序时,第一个实例会创建锁文件并继续执行程序,而后续的实例会检测到锁文件已存在并直接退出。当程序结束时,会删除锁文件,确保下次启动时能正常运行。
希望这可以解决你的问题,如果有任何疑问,请随时提问。