Java 读取为写入而锁定的文件
我使用文件锁定作为防止多次执行我的应用程序的手段:Java 读取为写入而锁定的文件,java,locking,Java,Locking,我使用文件锁定作为防止多次执行我的应用程序的手段: FileLock lock = fc.tryLock(); if (lock == null) { System.out.println("Error: The process is already running."); } 到目前为止还不错。现在我想写另一个进程,可以杀死第一个进程。 我想在锁文件中写入当前PID。第二个进程将验证锁是否在这里(意味着进程正在运行),读取文件并终止PID。读取前验证锁是强制性的,因为操作系统可能会回
FileLock lock = fc.tryLock();
if (lock == null) {
System.out.println("Error: The process is already running.");
}
到目前为止还不错。现在我想写另一个进程,可以杀死第一个进程。
我想在锁文件中写入当前PID。第二个进程将验证锁是否在这里(意味着进程正在运行),读取文件并终止PID。读取前验证锁是强制性的,因为操作系统可能会回收PID:主进程可能会停止,其PID会被另一个进程重用。问题是读取文件是不可能的,因为锁(而我认为锁只会阻止写入…)
下面是一个简化的代码:
public class TestLock {
public static void main(String[] args) throws Exception {
if (args.length == 1 && "kill".equals(args[0])) {
kill();
} else {
run();
}
}
private static void run() throws Exception {
File file = new File("test.lock");
try (FileOutputStream fos = new FileOutputStream(file)) {
FileLock lock = fos.getChannel().tryLock();
if (lock == null) {
System.err.println("Error: The process is already running.");
} else {
int pid = Integer.parseInt(ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
System.out.println("Process is launched with PID = " + pid);
fos.write(String.valueOf(pid).getBytes("UTF-8"));
while(true) {
Thread.sleep(3000);
System.out.println("App is running");
}
}
}
}
private static void kill() throws Exception {
File file = new File("test.lock");
if (!file.exists()) {
System.err.println("Error: The process is not running.");
return;
}
try (FileChannel fc = FileChannel.open(file.toPath(), StandardOpenOption.READ)) {
FileLock lock = fc.tryLock(0L, Long.MAX_VALUE, true);
if (lock == null) {
ByteBuffer bb = ByteBuffer.allocate(20);
fc.read(bb);
String pid = new String(bb.array(), "UTF-8").trim();
System.out.println(pid);
// Kill the process
} else {
System.err.println("Error: The process is not running.");
}
}
}
}
如果我在没有参数的情况下运行应用程序两次,第二个实例将显示“错误:进程已在运行”。如果我尝试在进程未运行时终止进程,则会得到“错误:进程未运行”。但如果我尝试终止正在运行的进程,则会得到IOException“该进程无法访问该文件,因为另一个进程已锁定该文件的一部分”
在其他线程中看到锁只是建议性的(如果我理解正确的话,如果没有检查就不会真正锁定),我尝试删除锁检查并在kill方法中使用一个简单的文件读取器,但我得到了相同的错误。(无论如何,我宁愿不这样做,因为PID重用,如前所述)