Java:如何创建一个仅在其实例不存在时才启动并在实例存在时调用该实例的应用程序?

Posted

技术标签:

【中文标题】Java:如何创建一个仅在其实例不存在时才启动并在实例存在时调用该实例的应用程序?【英文标题】:Java: How can I create an application that will only start if an instance of it doesn't exist and call the instance if it does exist? 【发布时间】:2016-10-01 09:25:45 【问题描述】:

我正在尝试使用 Java 创建一个程序,该程序一次只能运行一个实例。 我正在使用 Sockets 和 ServerSockets 来尝试实现这一点。

程序的工作原理是:

main方法会检查是否有任何参数被传递,它会尝试将第一个参数写入服务器,如果失败则意味着这是唯一运行的实例,因此它会打开ServerSocket并然后开始框架。如果它没有失败,那么应用程序已经在运行,所以它应该发送字符串并且其他实例应该能够读取并处理它。

主要方法如下:

public static void main(String[] args) 
    String fileName = null;
    if (args.length >= 1) 
        fileName = args[0];
    
    if (Singleton.sendSignal(fileName)) 
        Frame.getFrame().open(fileName);
        Singleton.checkInput();
    

这是服务器类:

public class Singleton 
    private static final int portNumber = 4243;
    private static ServerSocket serverSocket;
    private static Socket clientSocket;
    private static Socket echoSocket;

    public static boolean sendSignal() 
        try 
            echoSocket = new Socket(InetAddress.getLocalHost().getHostName(), portNumber);
            PrintWriter out = new PrintWriter(echoSocket.getOutputStream(), true);
            out.write("Open\n");
            out.close();
            close();
            return false;
         catch (Exception e) 
            close();
            return true;
        
    

    public static void checkInput() 
        try 
            renewReader();
         catch (Exception e) 
            close();
        
    

    public static void renewReader() throws Exception 
        serverSocket = new ServerSocket(portNumber);
        clientSocket = serverSocket.accept();
        BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
        String inputLine = in.readLine();
        if (inputLine.equals("Open")) 
            Widget.getInstance().setVisible(true);
        
        close();
        renewReader();
    

    public static void close() 
        try 
            serverSocket.close();
         catch (Exception e) 
        
        try 
            clientSocket.close();
         catch (Exception e) 
        
        try 
            echoSocket.close();
         catch (Exception e) 
        
    


虽然此代码的一半有效(一次只运行一个实例),但只有第一组数据被传递,然后程序停止读取。如何让套接字一直监听直到程序关闭?

【问题讨论】:

【参考方案1】:

我是你的 checkInput() 方法,你在这里接受一次客户端连接。试试这样的:

public static void checkInput() 
   
     //do something here
     serverSocket = new ServerSocket(portNumber);
     //wait for request from client.
     Socket clientSocket = serverSocket.accept();
     //
     // do your processing here

     // call checkInput method again.
     checkInput();

一旦另一个实例启动,服务器将接受请求,进行处理,然后再次开始等待更多请求(为此我们再次调用 cehckInput)。

也在你的 main() 中添加这个:

public static void main(String[] args) 

    String fileName = null;
    if (args.length >= 1) 
        fileName = args[0];
    
    if (Singleton.sendSignal(fileName)) 
    
        Frame.getFrame().open(fileName);

        // start the server in a thread so that main method can continue on
        new Thread()
        
           public void run()
           
                Singleton.checkInput();
           
        .start();
    

    // do your other tasks.

在程序终止时,您的套接字将自动关闭。此外,如果您想显式关闭套接字,您可以添加一个关闭挂钩来关闭它。 一个简单的钩子看起来像这样。

Runtime.getRuntime().addShutdownHook(your thread that will close sockets);

【讨论】:

是否需要新线程?没有额外的程序可以正常工作。我的意思是什么都没有暂停。 我添加了线程以防万一,就好像您在 if 条件之后在 main() 方法中添加任何新代码一样,它不会执行,因为 checkInput() 方法被递归调用。因此,明智的做法是在线程中添加递归方法以防万一。是的,如果您确定之后 main 中不会再有任何代码行,您可以忽略线程部分。

以上是关于Java:如何创建一个仅在其实例不存在时才启动并在实例存在时调用该实例的应用程序?的主要内容,如果未能解决你的问题,请参考以下文章

android:Activity启动模式之singleTask

MFC 程序仅在某些 Windows 7 32 位计算机上存在运行时错误 R6025,并在其上安装 Visual Studio 后修复

Laravel:如何仅在模型关系存在时才查询模型关系

仅当目录或文件不存在时才重写规则

仅在列存在时才提供数据框列表

xml 显示变体图像,取决于来自Powersearch的过滤器//仅在其选项代码和powersearch文件代码相同时才有效。