Browse Source

main函数加锁,防止客户端重复开启

17491 2 weeks ago
parent
commit
5079dc1803
2 changed files with 83 additions and 0 deletions
  1. 11 0
      src/com/mes/App.java
  2. 72 0
      src/com/mes/util/LockUtil.java

+ 11 - 0
src/com/mes/App.java

@@ -3,6 +3,7 @@ package com.mes;
 import com.mes.core.StationConfig;
 import com.mes.ui.LoginFrame;
 import com.mes.ui.MainFrame;
+import com.mes.util.LockUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -18,6 +19,16 @@ public class App {
     private static MainFrame mainFrame;
 
     public static void main(String[] args) {
+        try {
+            if (LockUtil.getInstance().isAppActive()) {
+                log.warn("已有一个MES客户端实例正在运行,当前实例退出");
+                return;
+            }
+        } catch (Exception e) {
+            log.error("无法建立客户端单实例锁,程序退出", e);
+            return;
+        }
+
         log.info("========================================");
         log.info("通用MES客户端启动");
         log.info("========================================");

+ 72 - 0
src/com/mes/util/LockUtil.java

@@ -0,0 +1,72 @@
+package com.mes.util;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.channels.OverlappingFileLockException;
+import java.nio.file.StandardOpenOption;
+
+/**
+ * Prevents multiple instances of the client from running at the same time.
+ */
+public final class LockUtil {
+    private static final LockUtil INSTANCE = new LockUtil();
+    private static final String LOCK_FILE_NAME = "mesclient-op170.lock";
+
+    private FileChannel channel;
+    private FileLock lock;
+    private boolean checked;
+    private boolean active;
+
+    private LockUtil() {
+    }
+
+    public static LockUtil getInstance() {
+        return INSTANCE;
+    }
+
+    /**
+     * Returns true when another client instance already owns the lock.
+     */
+    public synchronized boolean isAppActive() {
+        if (checked) {
+            return active;
+        }
+        checked = true;
+        File lockFile = new File(System.getProperty("java.io.tmpdir"), LOCK_FILE_NAME);
+        try {
+            channel = FileChannel.open(lockFile.toPath(),
+                    StandardOpenOption.CREATE, StandardOpenOption.WRITE);
+            lock = channel.tryLock();
+            active = lock == null;
+            if (!active) {
+                Runtime.getRuntime().addShutdownHook(new Thread(this::release, "mesclient-lock-release"));
+            }
+        } catch (OverlappingFileLockException | IOException e) {
+            active = true;
+            release();
+        }
+        return active;
+    }
+
+    private synchronized void release() {
+        try {
+            if (lock != null && lock.isValid()) {
+                lock.release();
+            }
+        } catch (IOException ignored) {
+            // The process is exiting; there is nothing useful to recover here.
+        } finally {
+            try {
+                if (channel != null && channel.isOpen()) {
+                    channel.close();
+                }
+            } catch (IOException ignored) {
+                // The operating system releases the lock when the process exits.
+            }
+            lock = null;
+            channel = null;
+        }
+    }
+}