Manchmal sehe ich viele Anwendungen wie msn, Windows Media Player usw., die Einzelinstanzanwendungen sind (wenn der Benutzer ausgeführt wird, während die Anwendung ausgeführt wird, wird keine neue Anwendungsinstanz erstellt).
In C # verwende ich dafür die Mutex
Klasse, aber ich weiß nicht, wie ich das in Java machen soll.
java
single-instance
Fuangwith S.
quelle
quelle
Antworten:
Wenn ich diesen Artikel glaube , von:
Hinweis: Ahe erwähnt im Kommentar, dass die Verwendung
InetAddress.getLocalHost()
schwierig sein kann:getLocalHost
: IP-Adresse des Computers zurückgeben, vs. Tatsächliche Ergebnisse: Rückgabe127.0.0.1
.Oder Sie können
ManagementFactory
Objekt verwenden. Wie hier erklärt :JNLP bietet auch eine
SingleInstanceListener
quelle
InetAddress.getLocalHost()
dies in der DHCP-Umgebung nicht wie erwartet funktioniert, da die zurückgegebene Adresse davon abhängt, ob der Computer über Netzwerkzugriff verfügt. Die Lösung bestand darin, die Verbindung mit zu öffnenInetAddress.getByAddress(new byte[] {127, 0, 0, 1});
.InetAddress.getByName(null)
die Adresse der Loopback- Schnittstelle zurückgegeben. Ich denke, dies ist besser als die manuelle Angabe von 127.0.0.1, da dies theoretisch auch in Nur-IPv6-Umgebungen funktionieren sollte.Ich verwende die folgende Methode in der Hauptmethode. Dies ist die einfachste, robusteste und am wenigsten aufdringliche Methode, die ich je gesehen habe. Ich dachte, ich würde sie teilen.
quelle
Wenn die App. hat eine GUI, starte sie mit JWS und benutze die
SingleInstanceService
.Aktualisieren
Das Java-Plug-In (sowohl für Applets als auch für JWS-Apps erforderlich) wurde von Oracle nicht mehr unterstützt und aus dem JDK entfernt. Browserhersteller hatten es bereits aus ihren Browsern entfernt.
Diese Antwort ist also nicht mehr gültig. Lassen Sie es nur hier, um Leute zu warnen, die sich alte Unterlagen ansehen.
quelle
Ja, dies ist eine wirklich anständige Antwort für die Eclipse RCP Eclipse-Einzelinstanzanwendung unten ist mein Code
in application.java
quelle
Wir verwenden hierfür die Dateisperrung (eine exklusive Sperre für eine magische Datei im App-Datenverzeichnis des Benutzers), sind jedoch in erster Linie daran interessiert, zu verhindern, dass mehrere Instanzen jemals ausgeführt werden.
Wenn Sie versuchen, die zweite Instanz Befehlszeilenargumente usw. an die erste Instanz übergeben zu lassen, werden durch die Verwendung einer Socket-Verbindung auf localhost zwei Fliegen mit einer Klappe geschlagen. Allgemeiner Algorithmus:
quelle
Ich habe eine Lösung gefunden, eine etwas karikaturistische Erklärung, funktioniert aber in den meisten Fällen immer noch. Es verwendet die einfache alte Sperrdatei, um Dinge zu erstellen, aber in einer ganz anderen Ansicht:
http://javalandscape.blogspot.com/2008/07/single-instance-from-your-application.html
Ich denke, es wird eine Hilfe für diejenigen mit einer strengen Firewall-Einstellung sein.
quelle
Sie können die JUnique-Bibliothek verwenden. Es bietet Unterstützung für die Ausführung einer Java-Anwendung mit einer Instanz und ist Open Source.
http://www.sauronsoftware.it/projects/junique/
Unter der Haube werden Dateisperren im Ordner% USER_DATA% /. Junique erstellt und ein Server-Socket am zufälligen Port für jede eindeutige Anwendungs-ID erstellt, mit der Nachrichten zwischen Java-Anwendungen gesendet / empfangen werden können.
quelle
Unter Windows können Sie launch4j verwenden .
quelle
ManagementFactory-Klasse, die in J2SE 5.0 oder höher unterstützt wird
Aber jetzt benutze ich J2SE 1.4 und habe dieses gefunden http://audiprimadhanty.wordpress.com/2008/06/30/ensuring-one-instance-of-application-running-at-one-time/, aber ich teste es nie. Was denkst du darüber?
quelle
Sie können versuchen, die Einstellungs-API zu verwenden. Es ist plattformunabhängig.
quelle
Eine allgemeinere Möglichkeit, die Anzahl der Instanzen auf einem einzelnen Computer oder sogar einem gesamten Netzwerk zu begrenzen, ist die Verwendung eines Multicast-Sockets.
Mithilfe eines Multicast-Sockets können Sie eine Nachricht an eine beliebige Anzahl von Instanzen Ihrer Anwendung senden, von denen sich einige auf physisch entfernten Computern in einem Unternehmensnetzwerk befinden können.
Auf diese Weise können Sie viele Arten von Konfigurationen aktivieren, um Dinge wie zu steuern
Die Multicast-Unterstützung von Java erfolgt über das Paket java.net, wobei MulticastSocket & DatagramSocket die Hauptwerkzeuge sind.
Hinweis : MulticastSockets garantieren keine Zustellung von Datenpaketen. Verwenden Sie daher ein Tool, das auf Multicast-Sockets wie JGroups basiert . JGroups tut Garantie Lieferung aller Daten. Es ist eine einzelne JAR-Datei mit einer sehr einfachen API.
JGroups gibt es schon seit einiger Zeit und hat einige beeindruckende Anwendungen in der Industrie, zum Beispiel unterstützt es den Clustering-Mechanismus von JBoss, Daten an alle Instanzen eines Clusters zu senden.
Die Verwendung von JGroups und die Begrenzung der Anzahl der Instanzen einer App (auf einem Computer oder in einem Netzwerk, z. B. auf die Anzahl der Lizenzen, die ein Kunde gekauft hat) ist konzeptionell sehr einfach:
quelle
Sie können eine Speicherzuordnungsdatei öffnen und dann prüfen, ob diese Datei bereits geöffnet ist. Wenn es bereits geöffnet ist, können Sie von main zurückkehren.
Andere Möglichkeiten sind die Verwendung von Sperrdateien (Standard-Unix-Praxis). Eine weitere Möglichkeit besteht darin, etwas in die Zwischenablage zu legen, wenn main startet, nachdem überprüft wurde, ob sich bereits etwas in der Zwischenablage befindet.
Andernfalls können Sie einen Socket in einem Listen-Modus (ServerSocket) öffnen. Versuchen Sie zunächst, eine Verbindung zum Socket herzustellen. Wenn Sie keine Verbindung herstellen können, öffnen Sie einen Serversocket. Wenn Sie eine Verbindung herstellen, wissen Sie, dass bereits eine andere Instanz ausgeführt wird.
So kann so ziemlich jede Systemressource verwendet werden, um zu wissen, dass eine App ausgeführt wird.
BR, ~ A.
quelle
Ich habe dafür Sockets verwendet und je nachdem, ob sich die Anwendung auf der Client- oder der Serverseite befindet, ist das Verhalten etwas anders:
quelle
quelle
BEARBEITEN : Anstatt diesen WatchService-Ansatz zu verwenden, kann ein einfacher 1-Sekunden-Timer-Thread verwendet werden, um zu überprüfen, ob die Datei indicFile.exists () vorhanden ist. Löschen Sie es und bringen Sie die Anwendung zu Front ().
EDIT : Ich würde gerne wissen, warum dies abgelehnt wurde. Es ist die beste Lösung, die ich bisher gesehen habe. Beispielsweise schlägt der Server-Socket-Ansatz fehl, wenn eine andere Anwendung den Port bereits überwacht.
Laden Sie einfach Microsoft Windows Sysinternals TCPView herunter (oder verwenden Sie netstat), starten Sie es, sortieren Sie es nach "State", suchen Sie nach dem Zeilenblock "LISTENING", wählen Sie einen aus, dessen Remote-Adresse den Namen Ihres Computers enthält, und stecken Sie diesen Port in Ihren neuen Socket ()-Lösung. Bei meiner Implementierung kann ich jedes Mal einen Fehler verursachen. Und es ist logisch , weil es die Grundlage des Ansatzes ist. Oder was bekomme ich nicht darüber, wie ich das umsetzen soll?
Bitte informieren Sie mich, wenn und wie ich mich irre!
Meiner Ansicht nach - und ich bitte Sie, dies nach Möglichkeit zu widerlegen - wird den Entwicklern empfohlen, einen Ansatz im Produktionscode zu verwenden, der in mindestens einem von etwa 60000 Fällen fehlschlägt. Und wenn diese Ansicht richtig ist, kann es absolut nicht sein, dass eine vorgestellte Lösung, die dieses Problem nicht aufweist, wegen ihrer Codemenge herabgestuft und kritisiert wird.
Nachteile des Socket-Ansatzes im Vergleich:
Ich hatte gerade eine gute Idee, wie ich das Java-Kommunikationsproblem zwischen neuer Instanz und vorhandener Instanz so lösen kann, dass es auf jedem System funktioniert. Also habe ich diese Klasse in ungefähr zwei Stunden ausgepeitscht. Funktioniert wie ein Zauber: D.
Es basiert auf Roberts Dateisperrungsansatz (auch auf dieser Seite), den ich seitdem verwendet habe. Um der bereits laufenden Instanz mitzuteilen, dass eine andere Instanz versucht hat zu starten (aber nicht) ... wird eine Datei erstellt und sofort gelöscht, und die erste Instanz verwendet den WatchService, um diese Änderung des Ordnerinhalts zu erkennen. Ich kann nicht glauben, dass dies anscheinend eine neue Idee ist, wenn man bedenkt, wie grundlegend das Problem ist.
Dies kann leicht geändert werden, um nur die Datei zu erstellen und nicht zu löschen, und dann können Informationen darin eingefügt werden, die die richtige Instanz auswerten kann, z. B. die Befehlszeilenargumente - und die richtige Instanz kann dann das Löschen durchführen. Persönlich musste ich nur wissen, wann ich das Fenster meiner Anwendung wiederherstellen und an die Vorderseite senden musste.
Anwendungsbeispiel:
Hier ist die Klasse:
quelle
new ServerSocket()
mit einem Fangblock ist völlig ausreichend,Zu diesem Zweck habe ich eine Java-Bibliothek namens Unique4j geschrieben. Sie können es unter https://github.com/prat-man/unique4j sehen . Die Bibliothek ist auch in Maven Central für einfachen Zugriff und Integration verfügbar.
Es ist plattformübergreifend kompatibel und unterstützt Java 1.6+. Die Bibliothek ist unter Apache 2.0 lizenziert und eignet sich daher ideal für alle Open-Source- und Closed-Source-Projekte.
Es verwendet eine Kombination aus Dateisperren und dynamischen Port-Sperren, um Instanzen zu erkennen und zwischen ihnen zu kommunizieren, mit dem primären Ziel, nur eine Instanz ausführen zu lassen.
Im Folgenden finden Sie ein einfaches Beispiel für die Verwendung und die Funktionen von Unique4j. Die Bibliothek bietet mehr Anpassungen und Funktionen, die für mehr Features und Funktionen überschrieben werden können.
Ich habe es für eines meiner eigenen Projekte erstellt und es dann als Bibliothek veröffentlicht. Hoffe, jemand findet es nützlich.
quelle