Как реализовать единственное JAVA-приложение экземпляра?

87
задан Andrew Thompson 24 June 2012 в 17:59
поделиться

10 ответов

Если я верю этому статья :

наличие первой инстанции пытаются открыть сокет слушания в интерфейсе localhost. Если это в состоянии открыть сокет, предполагается, что это - первая инстанция приложения, которое будет запущено. В противном случае предположение - то, что экземпляр этого приложения уже работает. Новый экземпляр должен уведомить существующий экземпляр, что запуск был предпринят, затем выйдите. Существующий экземпляр вступает во владение после получения уведомления и запускает событие в слушателя, который обрабатывает действие.

Примечание: Ахе упоминает в комментарии, что использование InetAddress.getLocalHost() может быть хитрым:

  • это не работает как ожидалось в среде DHCP, потому что возвращенный адрес зависит от того, имеет ли компьютер доступ к сети.
    Решение состояло в том, чтобы открыть соединение с [1 134] InetAddress.getByAddress(new byte[] {127, 0, 0, 1}) ;
    , Вероятно, связанный с [1 113] ошибка 4435662 .
  • я также нашел ошибка 4665037 , который сообщает, чем ожидаемые результаты getLocalHost: возвратите IP-адрес машины, по сравнению с Фактическими результатами: возвратитесь 127.0.0.1.

удивительно иметь getLocalHost возврат 127.0.0.1 на Linux, но не на окнах.

<час>

Или можно использовать ManagementFactory объект. Как объяснено здесь :

getMonitoredVMs(int processPid) метод получает как параметр текущий PID приложения, и поймайте имя приложения, которое называют из командной строки, например, приложение было запущено от c:\java\app\test.jar путь, тогда переменная значения" c:\\java\\app\\test.jar". Таким образом, мы поймаем просто имя приложения на строке 17 из кода ниже.
После этого, мы ищем JVM другой процесс с тем же именем, если мы нашли его, и PID приложения отличается, это означает, что это - второй экземпляр приложения.

JNLP предлагает также SingleInstanceListener

60
ответ дан Community 24 November 2019 в 07:48
поделиться

Можно открыть Memory Mapped File и затем видеть, открыт ли тот файл уже. если это уже открыто, можно возвратиться из основного.

Другие пути должен использовать файлы блокировки (стандартная практика Unix). Еще один путь состоит в том, чтобы поместить что-то в буфер обмена, когда основные запуски после проверки, если что-то уже находится в буфере обмена.

Еще, можно открыть сокет в режиме прослушивания (ServerSocket). Сначала попытайтесь соединиться с сокетом hte; если Вы не можете соединиться, затем открыть serversocket., если Вы соединяетесь, то Вы знаете, что другой экземпляр уже работает.

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

BR, ~A

1
ответ дан anjanb 24 November 2019 в 07:48
поделиться

Вы могли попытаться использовать Предпочтительный API. Это независимо от платформы.

2
ответ дан Javamann 24 November 2019 в 07:48
поделиться

Класс ManagementFactory поддерживал в J2SE 5.0 или позже деталь

, но теперь я использую J2SE 1.4, и я нашел этот http://audiprimadhanty.wordpress.com/2008/06/30/ensuring-one-instance-of-application-running-at-one-time/ , но я никогда не тестирую. Что Вы думаете об этом?

2
ответ дан Fuangwith S. 24 November 2019 в 07:48
поделиться

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

, При попытке иметь второй экземпляр, передают командную строку args, и т.д.... к первой инстанции, затем использование сокетного соединения на localhost будет уничтожать двух птиц с одним камнем. Общий алгоритм:

  • На запуске, попытайтесь открыть слушателя на порте XXXX на localhost
  • , если сбой, откройте устройство записи для того порта на localhost и отправьте командную строку args, то завершите работу
  • иначе, послушайте на порте XXXXX на localhost. Когда получают командную строку args, обрабатывают их, как будто приложение было запущено с той командной строкой.
5
ответ дан Kevin Day 24 November 2019 в 07:48
поделиться

В Windows можно использовать launch4j.

4
ответ дан Jacek Szymański 24 November 2019 в 07:48
поделиться

Я записал библиотеку Java по имени Unique4j для этой самой цели. Вы видите его в https://github.com/prat-man/unique4j. Библиотека доступна на Знатоке, Центральном также для легкого доступа и интеграции.

Это межплатформенное совместимый и поддерживает Java 1.6 +. Библиотеке лицензируют под Apache 2.0, который делает ее идеалом для использования с любым проектом и открыто полученный и закрытый исходный код.

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

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

import tk.pratanumandal.unique4j.Unique;
import tk.pratanumandal.unique4j.exception.Unique4jException;

public class Unique4jDemo {

    // unique application ID
    public static String APP_ID = "tk.pratanumandal.unique4j-mlsdvo-20191511-#j.6";

    public static void main(String[] args) throws Unique4jException {
        // create unique instance
        Unique unique = new Unique(APP_ID) {
            @Override
            public void receiveMessage(String message) {
                // display received message from subsequent instance
                System.out.println(message);
            }

            @Override
            public String sendMessage() {
                // send message to first instance
                return "Hello World!";
            }
        };

        // try to obtain lock
        boolean lockFlag = unique.acquireLock();

        // perform long running tasks here
        ...

        // try to free the lock before exiting program
        boolean lockFreeFlag = unique.freeLock();
    }
}

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

0
ответ дан 24 November 2019 в 07:48
поделиться

I have found a solution, a bit cartoonish explanation, but still works in most cases. It uses the plain old lock file creating stuff, but in a quite different view:

http://javalandscape.blogspot.com/2008/07/single-instance-from-your-application.html

I think it will be a help to those with a strict firewall setting.

5
ответ дан 24 November 2019 в 07:48
поделиться

Я использовал для этого сокеты, и в зависимости от того, находится ли приложение на стороне клиента или на стороне сервера, поведение немного отличается:

  • Сторона клиента: если экземпляр уже существует (я не могу прослушивать определенный порт ) Я передам параметры приложения и выйду (вы можете выполнить некоторые действия в предыдущем случае), если нет, я запущу приложение.
  • сторона сервера: если экземпляр уже существует, я напечатаю сообщение и выйду, если нет, я запущу приложение.
1
ответ дан 24 November 2019 в 07:48
поделиться

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

private static boolean lockInstance(final String lockFile) {
    try {
        final File file = new File(lockFile);
        final RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
        final FileLock fileLock = randomAccessFile.getChannel().tryLock();
        if (fileLock != null) {
            Runtime.getRuntime().addShutdownHook(new Thread() {
                public void run() {
                    try {
                        fileLock.release();
                        randomAccessFile.close();
                        file.delete();
                    } catch (Exception e) {
                        log.error("Unable to remove lock file: " + lockFile, e);
                    }
                }
            });
            return true;
        }
    } catch (Exception e) {
        log.error("Unable to create and/or lock file: " + lockFile, e);
    }
    return false;
}
62
ответ дан 24 November 2019 в 07:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: