在java中限制应用程序的多个实例

时间:2011-05-26 06:42:13

标签: java swing multiple-instances single-instance

我想阻止在java中启动多个应用程序实例。我知道两种方法:

  1. 锁定文件
  2. 锁定插座
  3. 但哪一种更有效,更好用?我应该使用哪一个?

    也欢迎任何其他解决方案。

8 个答案:

答案 0 :(得分:3)

有一个名为jUnique的库,可以帮助您自己实现它。

答案 1 :(得分:2)

如果使用Java WebStart进行部署,则SingleInstanceService会执行此操作。

请参阅http://download.oracle.com/javase/6/docs/technotes/guides/javaws/developersguide/faq.html#218

答案 2 :(得分:1)

我的投票是锁定端口(我认为这是你的意思是套接字)。我不知道确切的原因。但事实上,在大多数实际项目中,我只是将其作为解决方案。虽然我很乐意听到其他方式。

答案 3 :(得分:1)

在回答您的问题时,端口解决方案将从机器中获取更多资源:
- 您将保持端口锁定:端口有限,您可能会发现防火墙或其他程序在同一端口上侦听时出现问题。
- 您需要一个活动线程

文件解决方案将使用来自机器的更少资源,以避免在运行时的addShutdownHook方法中永久锁定文件,以便删除文件。

答案 4 :(得分:1)

编辑:我尝试使用Win200864b(版本并不重要)和活着的JFrame并使用JFrame.DO_NOTHING_ON_CLOSE

移至toFront()或使用SystemTray中的Iconified
    public interface ApplicationStartedListener {

        void applicationStarted();

        void foreignApplicationStarted(String name);

        void messageArrived(Object obj);
    }

//

    import java.io.Serializable;

    public class ClassCheck implements Serializable {

        private static final long serialVersionUID = 1L;
        private String className = null;

        public ClassCheck() {
        }

        public ClassCheck(String className) {
            setClassName(className);
        }

        @Override
        public String toString() {
            return this.className;
        }

        public String getClassName() {
            return this.className;
        }

        public void setClassName(String className) {
            this.className = className;
        }
    }
//

    import java.awt.AWTException;
    import java.awt.BorderLayout;
    import java.awt.Frame;
    import java.awt.MouseInfo;
    import java.awt.Point;
    import java.awt.Robot;
    import java.awt.event.InputEvent;
    import java.io.File;
    import javax.swing.JFrame;
    import javax.swing.JTextField;
    import javax.swing.SwingUtilities;

    public class RunOnceFromFile {

        private SingleInstanceController sic = null;
        private JFrame frame;
        private Robot r;
        private JTextField tf;

        public RunOnceFromFile() {
            try {
                r = new Robot();
            } catch (AWTException ex) {
                ex.printStackTrace();
            }
            sic = new SingleInstanceController(new File(System.getProperty("java.io.tmpdir") + "Example.file"), "sic_example_application");
            if (sic.isOtherInstanceRunning()) {
                sic.sendMessageToRunningApplication("toFront");
                System.exit(0);
            } else {
                frame = new JFrame("TEST");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setSize(400, 300);
                tf = new JTextField("JTextFiled");
                frame.add(tf, BorderLayout.NORTH);
                frame.setExtendedState(Frame.ICONIFIED);
                frame.setExtendedState(Frame.NORMAL);
                frame.setExtendedState(frame.getExtendedState() | JFrame.ICONIFIED);
                frame.setExtendedState(frame.getExtendedState() & (~JFrame.ICONIFIED));
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
                sic.registerApplication();
                sic.addApplicationStartedListener(new ApplicationStartedListener() {

                    public void applicationStarted() {
                        Runnable doRun = new Runnable() {

                            public void run() {
                                frame.toFront();
                            }
                        };
                        SwingUtilities.invokeLater(doRun);
                    }

                    public void foreignApplicationStarted(final String name) {
                        Runnable doRun = new Runnable() {

                            public void run() {
                                frame.toFront();
                            }
                        };
                        SwingUtilities.invokeLater(doRun);
                    }

                    public void messageArrived(final Object obj) {
                        Runnable doRun = new Runnable() {//activateWindow(frame);

                            public void run() {
                                frame.toFront();
                            }
                        };
                        SwingUtilities.invokeLater(doRun);
                    }

                    private void activateWindow(JFrame frame) {
                        frame.setExtendedState(Frame.ICONIFIED);
                        frame.setExtendedState(Frame.NORMAL);
                        frame.setAlwaysOnTop(true);
                        frame.setAlwaysOnTop(false);
                        Point location = MouseInfo.getPointerInfo().getLocation();
                        Point locationOnScreen = frame.getLocationOnScreen();
                        r.mouseMove(locationOnScreen.x + 100, locationOnScreen.y + 10);
                        r.mousePress(InputEvent.BUTTON1_MASK);
                        r.mouseRelease(InputEvent.BUTTON1_MASK);
                        r.mouseMove(location.x, location.y);
                    }
                });
            }
        }

        public static void main(String[] args) {
            RunOnceFromFile roff = new RunOnceFromFile();
        }
    }
//

    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.File;
    import java.io.FileReader;
    import java.io.FileWriter;
    import java.io.IOException;
    import java.io.ObjectInputStream;
    import java.io.ObjectOutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.util.ArrayList;

    public class SingleInstanceController {

        private String appname = null;
        private Socket client = null;
        private File file = null;
        private ArrayList<ApplicationStartedListener> listener = null;
        private ObjectInputStream ois = null;
        private ObjectOutputStream oos = null;
        private boolean result = false;
        private ServerSocket server = null;

        public SingleInstanceController(String appname) {
            this(new File(System.getProperty("java.io.tmpdir") + "/923jhakE53Kk9235b43.6m7"), appname);
        }

        public SingleInstanceController(File file, String appname) {
            this.file = file;
            this.appname = appname;
            this.listener = new ArrayList<ApplicationStartedListener>();
        }

        public void addApplicationStartedListener(ApplicationStartedListener asl) {
            this.listener.add(asl);
        }

        public void removeApplicationStartedListener(ApplicationStartedListener asl) {
            this.listener.remove(asl);
        }

        public boolean isOtherInstanceRunning() {
            if (!this.file.exists()) {
                return false;
            }
            return sendMessageToRunningApplication(new ClassCheck(this.appname));
        }

        public boolean sendMessageToRunningApplication(final Object obj) {
            this.result = false;
            try {
                this.client = new Socket("localhost", getPortNumber());
                new Thread(new Runnable() {

                    public void run() {
                        try {
                            SingleInstanceController.this.oos = new ObjectOutputStream(SingleInstanceController.this.client.getOutputStream());
                            SingleInstanceController.this.ois = new ObjectInputStream(SingleInstanceController.this.client.getInputStream());
                            SingleInstanceController.this.oos.writeObject(obj);
                            SingleInstanceController.this.oos.flush();
                            SingleInstanceController.this.result = SingleInstanceController.this.ois.readBoolean();
                        } catch (IOException e) {
                            SingleInstanceController.this.result = false;
                        }
                    }
                }).start();
                for (int i = 0; i < 10; i++) {
                    if (this.result == true) {
                        break;
                    }
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                this.client.close();
                return this.result;
            } catch (IOException e) {
                return false;
            }
        }

        public boolean registerApplication() {
            try {
                if (!this.file.exists()) {
                    if (!this.file.getParentFile().mkdirs() && !this.file.getParentFile().exists()) {
                        return false;
                    }
                    if (!this.file.createNewFile()) {
                        return false;
                    }
                }
                BufferedWriter wuffy = new BufferedWriter(new FileWriter(this.file));
                int port = getFreeServerSocket();
                if (port != -1) {
                    startServer();
                }
                wuffy.write(String.valueOf(port));
                wuffy.close();
                return true;
            } catch (IOException e) {
                return false;
            }
        }

        protected void messageArrived(Object obj) {
            for (ApplicationStartedListener asl : this.listener) {
                asl.messageArrived(obj);
            }
        }

        protected void applicationStartet() {
            for (ApplicationStartedListener asl : this.listener) {
                asl.applicationStarted();
            }
        }

        protected void foreignApplicationStarted(String name) {
            for (ApplicationStartedListener asl : this.listener) {
                asl.foreignApplicationStarted(name);
            }
        }

        private int getPortNumber() {
            try {
                BufferedReader buffy = new BufferedReader(new FileReader(this.file));
                int port = Integer.parseInt(buffy.readLine().trim());
                buffy.close();
                return port;
            } catch (Exception e) {
                return -1;
            }
        }

        private void startServer() {
            new Thread(new Runnable() {

                public void run() {
                    while (true) {
                        try {
                            SingleInstanceController.this.client = SingleInstanceController.this.server.accept();
                            if (SingleInstanceController.this.client.getInetAddress().isLoopbackAddress()) {
                                new Thread(new Runnable() {

                                    public void run() {
                                        try {
                                            SingleInstanceController.this.oos = new ObjectOutputStream(SingleInstanceController.this.client.getOutputStream());
                                            SingleInstanceController.this.ois = new ObjectInputStream(SingleInstanceController.this.client.getInputStream());
                                            Object obj = SingleInstanceController.this.ois.readObject();
                                            if (obj instanceof ClassCheck) {
                                                if (obj.toString().equals(SingleInstanceController.this.appname)) {
                                                    SingleInstanceController.this.oos.writeBoolean(true);
                                                    applicationStartet();
                                                } else {
                                                    SingleInstanceController.this.oos.writeBoolean(false);
                                                    foreignApplicationStarted(obj.toString());
                                                }
                                            } else {
                                                messageArrived(obj);
                                                SingleInstanceController.this.oos.writeBoolean(true);
                                            }
                                            SingleInstanceController.this.oos.flush();
                                            SingleInstanceController.this.client.close();
                                        } catch (IOException e) {
                                            e.printStackTrace();
                                        } catch (ClassNotFoundException e) {
                                            e.printStackTrace();
                                        }
                                    }
                                }).start();
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }).start();
        }

        private int getFreeServerSocket() {
            for (int i = 2000; i < 10000; i++) {
                try {
                    this.server = new ServerSocket(i);
                    return i;
                } catch (IOException ignore) {
                }
            }
            return -1;
        }
    }

答案 5 :(得分:0)

serversocket解决方案是跨平台的。并且不会受到程序崩溃和重置锁定的影响。

答案 6 :(得分:0)

文件锁定是更好的方法。在用户的主目录中创建文件时,这仍然可以在多用户环境中使用。

我遇到了 - JUnique--没有机会使用它 http://www.sauronsoftware.it/projects/junique/manual.php

答案 7 :(得分:0)

我知道这个问题很老了,但我现在必须解决同样的问题。我更喜欢套接字解决方案,因为我从未想过这样的任务应该与文件系统有任何关系。最好解决内存中的问题,而不是我认为的文件系统。