【问题标题】:Keep singleton instance of java application保留java应用程序的单例实例
【发布时间】:2025-12-06 12:55:01
【问题描述】:

我有一个 jar 文件,它在执行时显示 JFrame。 我不想允许重复执行我的 Jar 文件。 每次在创建框架之前,使用 Java 我想检查 Jar 是否已经在执行。如果我的应用程序。屏幕上已经有一个实例,我想把它放在前面。

我该怎么做? 请给我一个方法。

【问题讨论】:

  • 只有两种方法可以实现:文件侦听器或创建一个设置了布尔标志的 bean。
  • 部署 Java 桌面应用程序的最佳方式是使用 Java Web Start。它包括许多方便的 API,包括 SingleInstanceService,其中 "..允许在 Java Web Start 下启动的应用程序将自己注册为单例,并在用户尝试启动它们的新实例时传递新参数集。"
  • “你只有 2 种方法来实现它:” 著名的遗言。看我的评论。它可能使用其中任何一种方式,或者完全使用其他方式(例如保护ServerSocket),但只要它在 x 平台上可靠运行,为什么还要担心实现细节?

标签: java swing jframe single-instance


【解决方案1】:

Java 中没有用于单个应用程序实例的常规方法。 但是,您可以使用Socket 编程技术来实现您的目标。

创建实例时,它会尝试侦听ServerSocket。如果它可以打开ServerSocket,则意味着没有另一个应用程序实例。因此,它使ServerSocket 保持活动状态,直到程序关闭。如果它无法打开 ServerSocket,则意味着应用程序已经有另一个实例。因此,您可以静默退出应用程序。 此外,您无需在关闭应用程序时重置设置。

试试下面的例子

public class SingletonApplication extends JFrame implements Runnable {

    //count of tried instances
    private int triedInstances = 0;
    //the port number using
    private static final int PORT = 5555;

    public static void main(String[] args) {
        SingletonApplication application = new SingletonApplication();
        application.setTitle("My Singleton Application");
        application.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        application.setSize(500, 500);
        application.setVisible(true);
    }

    public SingletonApplication() {
        super();

        //run socket listening inside a thread
        Thread thread = new Thread(this);
        thread.start();
    }

    @Override
    public void run() {
        try {
            //create server socket
            ServerSocket serverSocket = new ServerSocket(PORT);

            //listing the socket to check new instances
            while (true) {
                try {
                    //another instance accessed the socket
                    serverSocket.accept();
                    //bring this to front
                    toFront();

                    //change the title (addtional);
                    triedInstances++;
                    setTitle("Tried another instances : " + triedInstances);
                } catch (IOException ex) {
                    //cannot accept socket
                }
            }
        } catch (IOException ex) {
            //fail if there is an instance already exists
            try {
                //connect to the main instance server socket
                new Socket(InetAddress.getLocalHost(), PORT);
            } catch (IOException ex1) {
                //do nothing
            } finally {
                //exit the system leavng the first instance
                System.exit(0);
            }
        }
    }
}

编辑:

另外:它可以通过客户端Socket将运行时参数传递给应用程序的主实例。因此,可以使主实例执行所需的任务,例如打开文件或播放在调用 accept() 方法时添加一些额外的代码来读取接受的SocketInputStream

【讨论】:

    【解决方案2】:

    我也有同样的情况。

    我所做的是我曾经在write 模式下打开file,在关闭应用程序时打开delete file

    通过这样做,我有一个已知的证据证明我的程序正在运行。

    每次我打开应用程序时,我都会检查该文件是否存在,如果我找到我的文件,它正在运行,然后我会提醒他

    “一个实例已经在运行”。

    即使有人试图删除该文件,它也会说它已在另一个应用程序中打开。

    【讨论】:

    • 如果您的应用程序意外关闭,您将无法永久运行该应用程序。并且您不能将应用程序置于最前面。
    【解决方案3】:

    我也使用了一个套接字,通过 RMI。

    应用程序是 RMI 主机/服务器,在端口上接受远程方法调用。

    总的来说,在启动时尝试作为 RMI 客户端在该端口上获取 RMI 服务器。 是否有人通过命令行参数进行远程调用(例如打开另一个文档)。然后退出。

    作为被调用远程方法的服务器,使用窗口的toFront() 将应用程序带到前面。

    【讨论】:

      【解决方案4】:

      JUnique 完成第一部分——阻止同一程序的多个实例。让现有实例出现在前面是我不知道如何处理的另一项任务。

      【讨论】: