COM-Zugriff per Singleton für mehrere Threads - unmöglich?

xck3001

Grünschnabel
Hallo,

ich greife per Java auf eine Windows-COM-Anwendung zu. Um nicht bei jedem Zugriff eine neue Verbindung aufbauen zu müssen, kapsele ich die Verbindung in einem Singleton Pattern. Das funktioniert sehr gut: Zugriffe aus dem Haupt-Thread des Programms gehen problemlos.

Allerdings will ich jetzt auch aus einem zweiten Thread auf das Singleton zugreifen und die COM-Verbindung nutzen. Dabei gibt es aber Probleme:

Obwohl ich laut hashCode() und diverser Variablenattribute eindeutig zur korrekten Singleton-Instanz gelange, scheint die COM-Verbindung nicht nutzbar zu sein, solange ich nicht im neuen Thread ebenfalls eine neue COM-Verbindung aufbaue. Es ist also ganz eindeutig ein Unterschied, ob ich aus dem Hauptthread oder aus dem Zweitthread auf das Singleton zugreife.

Das widerspricht ein wenig meinem Verständnis des Singleton Patterns: Sollte es für die Verarbeitung im Singleton nicht eigentlich völlig egal sein, von wo ich auf das Singleton zugreife? Wo liegt denn der Unterschied bei einem Zugriff aus einem zweiten Thread?

Zur Verdeutlichung hier mal der grobe Aufbau des Singletons
Code:
public class ComSingleton {
	private static final ComSingleton INSTANCE = new ComSingleton();

	private ComConnection connection;

	private ComSingleton() {
	}

	public static getInstance() {
		return INSTANCE;
	}

	public void connect() {
		// neue COM-Verbindung
		connection = new ComConnection();
	}

	public Data getComData() {
		// COM-Daten auslesen und ausgeben
		return connection.getSomeData();
	}
}

Das hier funktioniert:
Code:
//im Hauptthread
ComSingleton.getInstance().connect();
Data data = ComSingleton.getInstance().getComData();

Das hier funktioniert nicht:
Code:
//im Hauptthread
ComSingleton.getInstance().connect();
startNewThread();

//im Zweitthread
// fügt man diese Zeile hinzu, geht es: ComSingleton.getInstance().connect();
Data data = ComSingleton.getInstance().getComData();
 
Tut mir Leid, wenn ich was falsches geschrieben habe. Man lernt nie aus ich hab den Post mal abgeändert damit keine Verwirrung entsteht.

Gruss

Ben
 
Zuletzt bearbeitet von einem Moderator:
Wenn es so einfach wäre, wäre ich froh ;)

Das Pattern ist so meines Wissens richtig, siehe auch Wikipedia.
Dadurch dass die Instanz genau wie getInstance() statisch ist, kann nur eine Instanz existieren. Ein Singleton eben. Diese Variante hier hat den Vorteil dass man keine synchronized Methoden benötigt.

Ich greife übrigens auf jeden Fall auf die gleiche Instanz zu, weil in beiden Threads ComSingleton.getInstance().isConnected dann true ist.


Was in meinem Mock-Code hier allerdings fehlt ist der Return-Datentyp bei getInstance, der muss natürlich ComSingleton sein. Der Fehler ist aber nur hier im Dummy-Code.
 
Hallo,

der Aufbau des Singletons scheint auch mir korrekt zu sein. Vermutlich ist das Problem daher eher bei COM zu suchen. Ich kenne mich damit nicht wirklich aus, aber beim Überfliegen einiger Seiten zu dem Thema bin ich auf die Stichworte STA (Single Threading Apartment) und MTA (Multi Threading Apartment) gestoßen. Vielleicht hilft es ja, in die Richtung weiter zu forschen (und ggf. das Thema in ein passenderes Unterforum verschieben zu lassen, weil mit Java an sich hat es ja anscheinend nichts zu tun).

Grüße,
Matthias
 
OK, ich vermute auch dass irgendwo da der Hund begraben ist. Werde mal ein wenig in der Richtung nachgoogeln.

Danke soweit für die Hilfe!
 
Hi,

@kaMii, Das Pattern ist schon Richtig angewand, da es die Instancevariable als Static gekennzeichnet ist wird diese nur einmal zugewiesen :-)

@xck3001. Ich würde auch connection als Static declarieneren und im Head der Klasse inizialisieren damit nicht ausfersehen noch eine Verbindung aufgebaut wird, imo kann man durch erneuten aufruf von connect() eine neue Verbindung aufbauen, leider kann ich Dein Hauptproblem nicht nachvollziehen ( kein Win zur hand :-))...hast Du mal die Adressen der connection verglichen?

hmf
 
Also dass die Verbinding doppelt aufgebaut wird schließe ich mal aus, connect() wird nur am Anfang in der main() Methode aufgerufen.
Ich denke Matthias hatte da schon den richtigen Riecher, nach ein wenig einlesen sieht das genau nach meinem Problem aus. Da muss ich mich erstmal ein wenig mit STA bzw. MTA auseinandersetzen.

Leider ist COM-Unterstützung von Java nicht besonders ausgereift. Es gibt einige kleinere Projekte (ich benutze JACOB), aber sonderlich ausgereift scheint das alles nicht zu sein.
 
Ansonsten könnte man auch mit der Kirche ums Dorf ziehen und den COM - Zugriff über eine C Bibliothek realisieren...diese kann man relativ bequem in Java einbinden, ist aber auch nicht grad ne elegante Lösung

hmf
 
Zurück