Вопрос-ответ

How to implement a single instance Java application?

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

Иногда я вижу много приложений, таких как msn, проигрыватель Windows media и т.д., Которые являются приложениями с одним экземпляром (когда пользователь выполняет во время работы приложения, новый экземпляр приложения не создается).

В C # я использую Mutex class для этого, но я не знаю, как это сделать в Java.

Переведено автоматически
Ответ 1

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

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;
}
Ответ 2

Если я верю этой статье, по :


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


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



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



  • Я также обнаружил ошибку 4665037, которая сообщает о результатах, отличных от ожидаемых, getLocalHost: возвращает IP-адрес компьютера по сравнению с Фактическими результатами: возвращает 127.0.0.1.


удивительно иметь getLocalHost return 127.0.0.1 в Linux, но не в Windows.



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


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


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

Ответ 3

Если приложение. имеет графический интерфейс, запустите его с помощью JWS и используйте SingleInstanceService.

Обновить

Подключаемый модуль Java (необходимый как для апплетов, так и для приложений JWS) устарел Oracle и был удален из JDK. Производители браузеров уже удалили его из своих браузеров.

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

Ответ 4

Вы можете использовать библиотеку JUnique. Она обеспечивает поддержку запуска java-приложения с одним экземпляром и имеет открытый исходный код.

http://www.sauronsoftware.it/projects/junique/


Библиотека JUnique может использоваться для предотвращения одновременного запуска пользователем нескольких экземпляров одного и того же Java-приложения.


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


public static void main(String[] args) {
String appId = "myapplicationid";
boolean alreadyRunning;
try {
JUnique.acquireLock(appId, new MessageHandler() {
public String handle(String message) {
// A brand new argument received! Handle it!
return null;
}
});
alreadyRunning = false;
} catch (AlreadyLockedException e) {
alreadyRunning = true;
}
if (!alreadyRunning) {
// Start sequence here
} else {
for (int i = 0; i < args.length; i++) {
JUnique.sendMessage(appId, args[0]));
}
}
}

Под капотом оно создает блокировки файлов в папке %USER_DATA%/.junique и создает серверный сокет со случайным портом для каждого уникального AppID, который позволяет отправлять / получать сообщения между java-приложениями.

2023-10-17 00:07 java