【问题标题】:check for single instance java program [duplicate]检查单实例java程序[重复]
【发布时间】:2011-11-22 07:47:28
【问题描述】:

我有一个 Java 程序(带有一个 swing gui),我希望只有一个实例存在。如果它试图打开程序的另一个实例,我希望将当前实例带到前台。

我该怎么做?

提前致谢。

【问题讨论】:

标签: java swing


【解决方案1】:

使用Java Web Start 启动应用程序并实现JNLP APISingleInstanceService。这是demo. of the SingleInstanceService

如果它试图打开程序的另一个实例,我希望将当前实例带到前台。

将其连接到 SingleInstanceListenernewActivation(String[]) 方法中。它将传递为新发布提供的任何参数。现有实例决定如何处理新参数(例如更改文件、添加新选项卡、忽略..)

【讨论】:

    【解决方案2】:

    您可以使用 ShutDownHook 和锁定文件来完成此操作,请参见这个简单的 example

    我认为这是最简单的方法...

    【讨论】:

    • 我同意。这可能是最简单的实现方法。这是我一直在使用的。启动时有一个小技巧可以绕过 Windows 上的文件删除错误。
    【解决方案3】:

    Java 中没有 prev-instance,但您可以在 temp(或 /var/run)目录中创建一个 pid 文件。 (并将其设置为File.deleteOnExit() 在退出时无论如何都要清理它)

    要将现有窗口置顶,您可以自己通知程序,通过命名管道、unix 套接字或 java 远程方法调用等。一个简单而肮脏的方法是写入一个小文件,比如$TEMP/foobar-app.bring-to-top ,并且程序应该定期轮询这个小文件,如果它存在,将窗口置于顶部并删除这个小文件。

    我猜 Java 无法处理信号,即 kill -HUP PID 可能不适用于 Java 应用程序。即使可以,也不是每个操作系统都有信号。

    【讨论】:

      【解决方案4】:

      我用一个 Socket 和一个 ServerSocket 做过一次:


      首先,当您启动应用程序时,请在某个端口上侦听ServerSocket,例如4004。诀窍是检查它是否抛出IOException。如果是这样,则说明有另一个应用程序正在运行,或者该端口已被另一个应用程序使用(check this list for commonly used ports;请注意 TCP 和 UDP 端口不会相互阻塞),否则您可以继续启动应用程序。如果某个实例当前正在运行,您可能希望通过连接 TCP Socket 来通知它(这可以保证您的连接到达;UDP 不会)。

      这是一个例子:

      ServerSocket ss = null;
      try {
          ss = new ServerSocket(4004);
      } catch (IOException ex0) {
          // Port either occupied by your application or a foreign one
          // -> Connect
          Socket s = null;
          try {
              s = new Socket();
          } catch (Exception ex1) {
              // Something went wrong
          }
          if (s != null) {
              // Send some singnal
          }
      }
      if (ss == null) {
          // Close or do something else
      }
      

      (我是凭记忆写的,所以有些地方可能是错的或者可以做得更好)。

      【讨论】:

        【解决方案5】:

        在 C# 中,您通常在 Applicaiton 启动时创建 Mutex。如果您无法创建/获取它,则该应用程序的另一个实例已经在运行。不幸的是,我不能 100% 确定这在 Java 中的行为是否相同,或者确切的语法是什么。

        希望这会有所帮助。

        【讨论】:

        • (Un)幸运的是,Java 互斥锁不会在进程之间共享。
        • @alf 感谢您的信息 - 每天都在学习新的东西...这让我的回答毫无用处,但也许还有另一个 C# 开发人员也不知道。
        • 不一定没用。想法就在那里。你只需要找到另一种方法来实现互斥锁。
        【解决方案6】:

        模式单音:

        class SingleInstance {
        private static SingleInstance instance;
        
        public SingleInstance getInstance() {
            if (instance==null)
                instance = new SingleInstance();
            return instance;
        }
        
        private SingleInstance() {
        //construct it!
        }
        }
        

        【讨论】:

        • 在应用程序中使用单例不会阻止应用程序的多个实例(即多个 JVM 实例)。
        • 这只对一个类加载器有帮助; OP 想要的东西更像是“计算机上只有一个实例”
        猜你喜欢
        • 2012-03-20
        • 2016-11-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-06
        • 1970-01-01
        相关资源
        最近更新 更多