Java Inter-Thread-Kommunikation

Krik

Fleet Admiral Pro
Registriert
Juni 2005
Beiträge
18.461
Moin zusammen,

ich habe vor ein Client-Server-Programm mit dieser Struktur zu bauen:

unbenannt-png.276048



Ich suche gerade nach einer geeigneten Weise, Nachrichten zwischen Threads und Netzwerkteilnehmer auszutauschen. Der Einfachheit halber sollten die Nachrichten zwischen Threads mehr oder weniger identisch zu den Nachrichten zwischen den Netzwerkteilnehmern sein.

- Mehrere Clienten sind mit einem Server verbunden.
- Der Server(-Thread) koordiniert das Weiterleiten der Nachrichten zwischen Clienten und einer Datenbank.
- Aus Teilen der Daten in der Datenbank werden Objekte erzeugt.
- Gibt es Änderungen in der Datenbank oder bei den Objekten, soll das jeweils andere ebenfalls die Änderung mitbekommen.
- Wenn die Clients auf die Objekte zugreifen, werden je nach Aktion weitere Threads gestartet, die im Hintergrund irgendwas verarbeiten. Diese generierten Threads greifen nur auf die Objekte zu.
- Die Nachrichten sollen beinhalten: Herkunft (bestimmtes Objekt oder Thread), Ziel (Objekt oder Thread) und Inhalt (Statuscode + manchmal Text).
- Es wird 0 bis ~10 Clients geben.
- Es gibt nur einen Server und nur eine Datenbank.
- Es gibt ~100 bis 300 Objekte.
- Pro Objekt werden 0 bis 3*Number_of_Clients Worker gestartet.

Irgendwie habe ich gerade ein Brett vor dem Kopf. Ich weiß nicht genau, wie ich die Kommunikation, die hier nötig ist, koordinieren und umsetzen soll.
Semaphoren verwenden? Das wären ziemlich viele, vielleicht etwas zu aufwendig.
Pipes? Erscheint mir irgendwie auch nicht so das passende.
Listener? Das könnte das beste sein.
Hierzu würde ich gerne eure Meinung hören. Vielleicht gibt es da ja etwas viel besseres.

Gruß, Laurin
 

Anhänge

  • Unbenannt.png
    Unbenannt.png
    11,9 KB · Aufrufe: 637
Kannt du mal eben ein kurzes Anwendungsbeispiel geben? Irgendwas einfaches "Client sagt Server er braucht bla bla bla, also ..."
Hilft mir beim Denken ^^

Zumindest für die Anderung Objects <-> DB hören sich Listener extrem sinnvoll an...
 
Ok, kein Problem.


Hier ein Beispiel:
Der Client fordert Informationen an. Dazu sendet er eine Nachricht an den Server mit den Parametern zB "Client-ID", "DB", "3,1000" (Code 3A [read], Index 1000 -> lese Index 1000). Der Server empfängt das und leitet es an die DB weiter. Die DB werkelt dann daraufhin.
Zwischendurch sendet der Client eine Aufforderung an ein Objekt, zB "Client-ID", "Object xy", "doWork". Der Server empfängt das und leitet es an das passende Objekt weiter. Das Objekt zerlegt die Nachricht und startet einen Worker-Thread. Der läuft dann eine Weile.
Jetzt ist die DB mit dem Lesen fertig und generiert eine Nachricht "DB", "Client-ID", "3B,1000,gelesene Daten" (Code 3B [read completed], Index 1000, Inhalt -> Inhalt des Index 1000). Der Server übermittelt die Nachricht an den Clienten, der damit dann irgendwas macht.
Der Worker-Thread arbeitet während dessen sein Zeug ab und fragt dabei auch mehrere andere Objekte ab. Er wird dann fertig und ändert dabei ein Objekt. Er schickt eine Nachricht heraus: "Object xy" (nicht Workerthread-ID[!]), "Client-ID", "didWork". Wie gehabt, wird die Nachricht durch den Server-Thread an den Clienten gesendet.
Da "Object xy" durch den Worker-Thread verändert wurde, schickt das Objekt eine Nachricht an die Datenbank: "Object xy", "DB", "saveValues etc.".

Dieses System soll gewährleisten, dass jede Änderung bei einem Objekt oder in der DB auch beim jeweils anderen Part bekannt gemacht wird. Desweiteren soll es keine Blockierungen geben. Wenn durch ein Objekt z ein Worker-Thread gestartet wurde, muss das Objekt auch weiterhin abfragbar sein. Genauso mit der DB.

Ich habe schon überlegt, Objekte und DB zu vereinen, also alles direkt über die DB laufen zu lassen. Das würdeaber ein Codemonster ergeben, der nicht gerade leicht zu warten ist.
 
Nachdem bis dato keine Antwort kam versuche ich die Frage mal näher zu beleuchten.

Im Allgemeinen scheint mit die Architektur nicht sonderlich gut zu sein. Vielleich seh ich aber auch die genialität darin nicht *gg*. Es wirkt teils auf mich als würdest du den Heiligen Gral auf diesem Gebiet suche. Multithreaded Global synced geschichten, wenn noch dazu eine Datenbank im Spiel ist sind ein heikles Thema. Dafür gibt es schlichtweg keine perfekte Möglichkeit ohne sich damit nicht andere Nachteile ins Boot zu holen.

Ich versuch jetzt einmal auf die Architektur ein zu gehen. Das was du Objecte nennst solltest du auf alle Fälle umbennen, so etwas ist einfach nicht gebräuchlich und vor allem in diesem Kontext ein schlechter Name. Grundlegend empfehle ich Projekte immer mit einer Layered architektur aufzuziehen. Ich geh jetzt einmal davon aus das du in dem was du Object nennst das Model und Service Logik verpacken willst was nicht sonderlich empfehlenswert ist. Das sollte daher aufgetrennt werden., Des Weiteren gehe ich jetzt einmal davon aus das alles außer Client auf der selben Maschine läuft. Ansonsten müsste man hier nochmal generell was an der Architektur drehen.
Ich empfehle folgenden Ablauf (nach derzeitigen wissensstand von dem was ich denke was du willst) Server bekommt von einem Client einen request und und startet die Abarbeitung von einer beliebigen Aufgabe. Bei deiner Beschreibunb kann ein "Object" mehrere Workerthreads haben was ich persönlich nur machen würde wenn die Workerthreads komplet unabhängig arbeiten können. Was bedeutet das, dass Ergebnis eines Workers nicht verändert wird durch eine Veränderung eines Anderens Threads. Würde da eher stark dazu tendieren das sequentiell zu machen. Ansonsten fängst du dir race conditions ein das es eine freude ist. Das führt dazu das es praktisch nicht mehr debugbar ist. Generell übergreifend würde ich mit Datenbank Isolation levels arbeiten.
Für die Kommunikation zwischen Client und Server würde ich wohl zu JAVA RMI.

Falls mehrere Stelle auf unterschiedlichen Maschinen laufen sollen. Ist mein Post weitesgehend hinfällig. Dann läuft das ganze richtung message oriented middleware / broker pattern etc. Welches Pattern genau hängt dann von der ausprägung ab.
Wenn das eben genannte notwendig ist und du nichts von den dingen verstehst die ich eben genannt hab, befürchte ich dir allerdings sagen zu müssen, dass die Aufgabe von den Fähigkeiten für dich wohl derzeit nicht sinnvoll lösbar ist. Was allerdings nichts schlimmes ist da begeben wir uns schon auf das Nivo eins Studenten mit Bachelor Abschluss(und ich kenne einen Haufen dies mit Bachelor auch ned können)
 
Danke für deine Antwort, die hat für mich etwas Licht in die Sache gebracht. :)


Ja, ich suche so etwas wie einen multithreaded-global-synced-holy-grail (tolles Wort! ^^). Eigentlich reicht mir eine Art Message-System, das alle Teile miteinander verbindet, sodass Anforderungen und Arbeitsergebnisse ausgetauscht werden können.

Ich weiß, dass "Objects" ein recht allgemeines Wort ist. Ich bin noch an der Konzeption des Programms. Die Objects bestehen aus recht unterschiedlichen Objekten, die zB teilweise vordefinierte Skripte abarbeiten und/oder Worker-Threads starten können - oder auch nichts davon. Die Worker-Threads sollen aber unabhängig davon auf alle "Objects" zugreifen können, deshalb habe ich sie für die Diskussion hier zusammengefasst.
Du hast ganz richtig vermutet, dass sich dahinter die Modal und Service Logik verbirgt.

Desweiteren hast du ebenfalls richtig vermutet, dass abgesehen von den Clients alles auf einer Maschine laufen soll.

Die Worker-Threads sind vollkommen unabhängig voneinander. Sie können und sollen sich nicht gegenseitig beeinflussen können. Die einzelnen Threads sollen nur Daten aus verschiedenen "Objects" lesen, diese auswerten und ggf. in einem "Object" später das Ergebnis ihrer Arbeit ablegen.
Sollte ein Ergebnis einen Client direkt betreffen, soll ihmzusätzlich eine Nachricht geschickt werden. Hier brauche ich das Message-System wieder.
Sequenzielle Abarbeitung der Thread-Aufgaben ist hier leider nicht gewünscht, da der Umfang sowie der zeitlich benötigte Aufwand unterschiedlich sind. Das würde es nur komplizierter machen.

Das, was du hinsichtlich der Datenbank vorgeschlagen hast (isolation), habe ich mir auch schon überlegt.

Bei RMI bin ich mir noch nicht sicher, ob es das richtige ist. Ok, es macht viele Dinge einfacher (zB das marshallen), aber hm... Ich muss da nochmal genauer darüber nachdenken.


Und keine Sorge, ich habe deinen Post verstanden. Mein Bachelor-Abschluss ist nämlich auch nicht mehr weit. ;)
Die Sache ist nur, dass ich bis jetzt noch nie ein System in dieser Größe und Komplexität aufgezogen habe. Mir fehlt einfach die Erfahrung, was sich hier am besten eignet.
Deshalb nochmal vielen Dank für deinen Post. :)


Edit:
Ich kam gerade auf den Gedanken, für die Nachrichtenübermittlung eine Message-Queue zu verwenden. Da wirft einfach jeder seinen Senf rein, der dann nach und nach an die verschiedenen Teilsysteme ausgeliefert wird.
 
Wie sieht es mit scala aus?
sofern du keine eingeschränlte umgebung hast(Scala braucht min 1 gb ram).

Oder was auch interessant sein könnte wäre jppf.
Wobei jppf mehr in richtung grid computing geht.
 
Vielleicht eine wichtige Frage.
Handelt es sich dabei um eine Übung auf der Uni, privatem interesse oder aus Beruflichen Gründen.
Auch wenns blöd klingt davon hängt die Lösung ab.
 
Ohne jetzt das Thema komplett durchgelesen zu haben, würde ich dir von dem Modell "1 (oder n) Thread pro Client" abraten. Das skaliert sich bei wachsender Clientanzahl eher schlecht. Stattdessen solltest du, so weit möglich, einen Threadpool einsetzen (mit nicht mehr Threads als die Maschine Prozessoren / Kerne hat) und anfallende Aufgaben dynamisch auf diese Threads verteilen.
 
@Funart
Das ist ein privates Projekt. Ich möchte daher auch nicht auf andere Sprachen als Java setzen. Eventuell setze ich das irgendwann dann auch mal in C# um.

@antred
Gute Idee! Ich werde mich in der Hinsicht mal einlesen.
Allerdings kann ich jetzt schon sagen, dass es mehr Threads als Prozessorkerne geben wird. Ich tippe auf etwas um bis zu 10 Worker- Threads bei 5 Usern.
 
Hast schon mal darüber nachgedacht einen Application Server zu verwenden?

Dann sparst dir einiges an Arbeit und bist vermutlich auch praxis relevanter.
 
Das geht weit über dem hinaus, was ich erreichen will. Zudem habe ich keinerlei Erfahrung mit Tomcat & Co.

Ich weiß, du meinst es nur gut, aber ich will nur ein wenig Hobby-Programmierung betreiben. ;)
 
Zurück
Oben