Ограничить несколько экземпляров приложения в Java - PullRequest
6 голосов
/ 26 мая 2011

Я хочу предотвратить запуск нескольких экземпляров приложения в Java.Я знаю 2 способа для этого:

  1. блокировка файла
  2. блокировка сокета

Но какой из них более эффективен и хорош в использовании?Какой из них я должен использовать?

Любые другие решения, чтобы сделать то же самое также приветствуются.

Ответы [ 8 ]

3 голосов
/ 26 мая 2011

Существует библиотека под названием jUnique , которая делает это и избавит вас от необходимости реализовывать ее самостоятельно.

2 голосов
/ 26 мая 2011

Если вы внедряете с Java WebStart, SingleInstanceService делает это.

См. http://download.oracle.com/javase/6/docs/technotes/guides/javaws/developersguide/faq.html#218

1 голос
/ 26 мая 2011

РЕДАКТИРОВАТЬ: я пытался это с Win200864b (версия не важна) и живой JFrame и переместить toFront () или Iconified в SystemTray с JFrame.DO_NOTHING_ON_CLOSE

    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;
        }
    }
1 голос
/ 26 мая 2011

В ответ на ваш вопрос, решение для порта сохранит больше ресурсов от машины:
- Вы будете держать порт заблокированным : порты ограничены, и вы можете столкнуться с проблемами с брандмауэрами или другими программами, прослушивающими тот же порт.
- Вам понадобится активная тема .

Файловое решение будет использовать меньше ресурсов компьютера, чтобы избежать блокировки файла навсегда, вам нужно добавить поток, чтобы удалить файл, в методе addShutdownHook из среды выполнения.

1 голос
/ 26 мая 2011

Мой голос идет о блокировке порта (я думаю, это то, что вы подразумеваете под сокетом).Я не знаю точную причину этого.Но на самом деле я сталкиваюсь только с этим как решение в большинстве практических проектов.Хотя я буду рад услышать альтернативные пути.

0 голосов
/ 18 февраля 2013

Я знаю, что этот вопрос довольно старый, но сейчас мне нужно решить ту же проблему. Я предпочитаю сокетное решение, потому что я никогда не думал, что такого рода задачи должны иметь какое-либо отношение к файловой системе. Я думаю, что лучше решать проблему в памяти, а не в файловой системе.

0 голосов
/ 26 мая 2011

Блокировка файлов - лучший способ сделать это.Когда вы создаете файл в домашнем каталоге пользователя, он все равно будет работать в многопользовательской среде.

Я сталкивался - JUnique - не было возможности использовать его http://www.sauronsoftware.it/projects/junique/manual.php

0 голосов
/ 26 мая 2011

решение serversocket является кроссплатформенным.И не будет уязвим для сбоя программы и сброса блокировки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...