
Fuangwith S.
En algún momento veo muchas aplicaciones como msn, Windows Media Player, etc. que son aplicaciones de instancia única (cuando el usuario ejecuta mientras la aplicación se está ejecutando, no se crea una nueva instancia de aplicación).
En C#, uso Mutex
class para esto, pero no sé cómo hacerlo en Java.
Utilizo el siguiente método en el método principal. Este es el método más simple, robusto y menos intrusivo que he visto, así que pensé en compartirlo.
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;
}

VonC
si creo esto artículopor :
hacer que la primera instancia intente abrir un socket de escucha en la interfaz localhost. Si puede abrir el socket, se supone que esta es la primera instancia de la aplicación que se inicia. De lo contrario, se supone que ya se está ejecutando una instancia de esta aplicación. La nueva instancia debe notificar a la instancia existente que se intentó un lanzamiento y luego salir. La instancia existente toma el control después de recibir la notificación y dispara un evento al oyente que maneja la acción.
Nota: Ahe menciona en el comentario que usando InetAddress.getLocalHost()
puede ser complicado:
- no funciona como se esperaba en un entorno DHCP porque la dirección devuelta depende de si la computadora tiene acceso a la red.
La solución fue abrir la conexión con InetAddress.getByAddress(new byte[] {127, 0, 0, 1})
;
Probablemente relacionado con error 4435662.
- también encontré error 4665037 que informa de los resultados esperados de
getLocalHost
: devuelve la dirección IP de la máquina, frente a los resultados reales: devuelve 127.0.0.1
.
es sorprendente tener getLocalHost
regreso 127.0.0.1
en Linux pero no en Windows.
O puede usar ManagementFactory
objeto. Como se explica aquí:
los getMonitoredVMs(int processPid)
El método recibe como parámetro el PID de la aplicación actual y captura el nombre de la aplicación que se llama desde la línea de comando, por ejemplo, la aplicación se inició desde c:\java\app\test.jar
ruta, entonces la variable de valor es “c:\\java\\app\\test.jar
“. De esta manera, capturaremos solo el nombre de la aplicación en la línea 17 del código a continuación.
Después de eso, buscamos en JVM otro proceso con el mismo nombre, si lo encontramos y el PID de la aplicación es diferente, significa que es la segunda instancia de la aplicación.
JNLP ofrece también una SingleInstanceListener

andres thompson
Si la aplicación. tiene una GUI, inícielo con JWS y use el SingleInstanceService
.
Actualizar
El complemento de Java (requerido tanto para los applets como para las aplicaciones JWS) quedó obsoleto por Oracle y se eliminó del JDK. Los fabricantes de navegadores ya lo habían eliminado de sus navegadores.
Así que esta respuesta está muerta. Solo lo dejo aquí para advertir a las personas que buscan documentación antigua.

Parvez Ahmad
Sí, esta es una respuesta realmente decente para la aplicación de instancia única eclipse RCP eclipse a continuación es mi código
en aplicación.java
if(!isFileshipAlreadyRunning()){
MessageDialog.openError(display.getActiveShell(), "Fileship already running", "Another instance of this application is already running. Exiting.");
return IApplication.EXIT_OK;
}
private static boolean isFileshipAlreadyRunning() {
// socket concept is shown at http://www.rbgrn.net/content/43-java-single-application-instance
// but this one is really great
try {
final File file = new File("FileshipReserved.txt");
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;
}
Usamos el bloqueo de archivos para esto (obtener un bloqueo exclusivo en un archivo mágico en el directorio de datos de la aplicación del usuario), pero estamos interesados principalmente en evitar que se ejecuten varias instancias.
Si está intentando que la segunda instancia pase argumentos de línea de comando, etc. a la primera instancia, entonces usar una conexión de socket en localhost matará dos pájaros de un tiro. Algoritmo general:
- En el lanzamiento, intente abrir el oyente en el puerto XXXX en localhost
- si falla, abra un escritor en ese puerto en localhost y envíe los argumentos de la línea de comando, luego apague
- de lo contrario, escuche en el puerto XXXXX en localhost. Cuando reciba argumentos de línea de comando, procéselos como si la aplicación se hubiera iniciado con esa línea de comando.

Icono
He encontrado una solución, una explicación un poco caricaturesca, pero aún funciona en la mayoría de los casos. Utiliza el antiguo archivo de bloqueo simple para crear cosas, pero en una vista bastante diferente:
http://javalandscape.blogspot.com/2008/07/single-instance-from-your-application.html
Creo que será de ayuda para aquellos con una configuración de firewall estricta.

kolobok
Puede usar la biblioteca JUnique. Proporciona soporte para ejecutar una aplicación Java de instancia única y es de código abierto.
http://www.sauronsoftware.it/projects/junique/
La biblioteca JUnique se puede utilizar para evitar que un usuario ejecute al mismo tiempo más instancias de la misma aplicación Java.
JUnique implementa bloqueos y canales de comunicación compartidos entre todas las instancias de JVM lanzadas por el mismo usuario.
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]));
}
}
}
Bajo el capó, crea bloqueos de archivos en la carpeta %USER_DATA%/.junique y crea un socket de servidor en un puerto aleatorio para cada ID de aplicación único que permite enviar/recibir mensajes entre aplicaciones Java.
Un enfoque muy simple con java NIO ver ejemplo completo stackoverflow.com/a/20015771/185022
– AZ_
16 de noviembre de 2013 a las 7:03