# Datenverteilung: Mehrere Threads verwenden?



## Antimon (30. Jun 2009)

Hallo zusammen,

folgendes Problem bewegt mich grade: Von einem Bussystem (CAN-Bus) bekomme ich Datenpakete über eine (serielle) Schnittstelle in den PC - diese möchte ich weiterverarbeiten. Im Bussystem sind mehrere Teilnehmer, die auch in meiner Software virtuell abgebildet sind. Kommen vom Bus Daten, werden die von den virtuellen Teilnehmern verarbeitet.

Momentan läuft es so ab: Ein Datenpaket kommt herein, es wird herausgesucht zu welchem der Teilnehmer es gehört und wird diesem zugestellt. Dieser kann dann die Daten analysieren und weiterverarbeiten, was je nach Dateninhalt auch etwas länger dauern kann. Da vom Bus schon mal 1000 Pakete in der Sekunde kommen können, kann es passieren dass es dauert bis die neuen Pakete weitergeleitet werden, da die ganze Geschichte einigermaßen zeitkritisch ist, kommt das dann hin- und wieder zu Problemen.

Um das Ganze zu optimieren habe ich mir überlegt, die Pakete an die virtuellen Teilnehmer jeweils in einem Thread weiterzuschicken, wenn dann bei einem die Verarbeitung etwas länger dauert (z.B. weil in der Zwischenzeit ein Dateizugriff geschieht, der etwas dauert), können die anderen Pakete parallel weiterverarbeitet werden.

Das ist zwar an sich schön, aber macht es nicht einfacher, denn die Threads müssen ja vielleicht auch synchronisiert werden, aber das wäre schon machbar. Was mich aber noch mehr stört, ist dass wegen jeder Nachricht ein Thread ausgeführt wird - wie ist das von der Performance her? Klar kann ich einen Thread Pool verwenden, aber jeder Thread muss doch initialisiert werden, könnte das den Performancegewinn wieder beeinträchtigen? Im dümmsten Fall könnten ja pro Sekunde 1000 Threads gestartet / beendet werden, ist das zu heftig? Wäre es dann doch effizienter, die Nachrichten in einem Thread nacheinander abarbeiten zu lassen und dann lieber die Abarbeitung irgendwie zu optimieren?


----------



## tuxedo (30. Jun 2009)

Du kannst einen Cached ThreadPool verwenden. Da wird dann selbstätig entschieden wieviele Threads parallel laufen. Laufen die Threads für 60sek. leer, werden sie aufgeräumt.

Du kannst aber auch einen "Fixed Thread Pool" verwenden. Allerdings würde ich da keine 1000 Threads reinpacken. Eher "Anzahl CPU Kerne * 2" Threads. Wenn alle Threads beschäftigt sind werden neue Aufgaben einfach gequeued und ausgeführt wenn ein Thread wieder frei wird.

Musst ausprobieren was performanter ist. Vllt. machst du's am besten konfigurierbar. Dann kann man später noch wechseln wenns nötig ist. 

- Alex


----------



## Gast2 (30. Jun 2009)

Moin,

tuxedo hat schon recht - um eine Queue kommst Du nicht herum

Klasse Bus nimmt Daten vom Bus entgegen ... entscheidet welcher Teilnehmer die Daten dann weiter gereicht bekommt ... das wird dann beim entsprechenden Teilnehmer in einen Queue geschoben (Synchronisation könnte vorteilhaft sein) ... jeder Teilnehmer schaut in einem eigenem Thread nach ob etwas im Queue steckt ... wenn ja, wird entsprechend verarbeitet

das Kritische sind die Threads ... selbst 1000 Threads halte ich für viel (und ich schmeise gerne mit Threads um mich) ... daher würde ich in jedem Teilnehmer mit einem Busy-Wait und einem Sleep() die Queue überwachen ... und auch in diesem Thread würde ich dann die Daten abarbeiten ... das Ganze hat den Zweifelhaften Vorteil das der Queue voll läuft, wenn zu viele Daten ankommen ... spart dir aber auch das Verwalten und Instanzieren von Threads ... letzteres kostet viel Zeit und kannst Du mittels Thread-Pool umgehen ... die Verwaltung bleibt aber (und damit Rechenzeit)

am besten eine abstrakte Klasse Daten erstellen, welche die Daten in Rohform (also Byte-Array) entgegen nimmt ... dann sind alle Queue's für die Teilnehmer gleich ... die erbende Klasse kann dann ja entsprechende Methoden bereitstellen um mit den Daten arbeiten zu können

hand, mogel


----------



## Antimon (1. Jul 2009)

Hmm warum bin ich da nicht gleich draufgekommen - danke fürs Augen öffnen, Jungs.

Bisher bin ich davon ausgegangen, dass die Nachrichten in einem Thread verteilt und dort auch bearbeitet werden - aber eigentlich kann jeder Empfänger seine eigene Queue haben und die abarbeiten... also Nachricht kommt vom Bus, wird im Empfängerthread entgegengenommen und in die Teilnehmer-Queues eingereiht - dann werden die über ein notify() informiert, dass was da ist und können das abarbeiten. Und die Threads der Teilnehmer könnte man ja als CachedThreadPool ausführen oder? Bzw. wenn die Threads nach 60 Sekunden aufgeräumt (=beendet?) werden, vielleicht eher nicht so toll, ich will ja eigentlich dass die wieder anlaufen, wenn nach 5 Minuten wieder was reinkommt...

Was ist dann für eine Strategie bei der Datenverteilung sinnvoll? Ich kenne die Absenderadresse vom Bus und kann die Nachricht dann eindeutig einem Empfänger zuordnen, deswegen würde ich behaupten, ist es sinnvoll, wenn ich erst den Empfänger raussuche und dann die Nachricht zustelle. Oder ist es doch besser ich arbeite mit Listenern, jeder Empfänger ist ein Listener und prüft dann selbst ob die Nachricht für ihn ist oder nicht? 

Dumm ist halt, dass es Nachrichten gibt, die allen Teilnehmern zugestellt werden müssen, aber das wär von der Effizient mit beiden Methoden gleich oder?


----------



## Gast2 (1. Jul 2009)

> Was ist dann für eine Strategie bei der Datenverteilung sinnvoll? Ich kenne die Absenderadresse vom Bus und kann die Nachricht dann eindeutig einem Empfänger zuordnen, deswegen würde ich behaupten, ist es sinnvoll, wenn ich erst den Empfänger raussuche und dann die Nachricht zustelle. Oder ist es doch besser ich arbeite mit Listenern, jeder Empfänger ist ein Listener und prüft dann selbst ob die Nachricht für ihn ist oder nicht?


von der Wartbarkeit her ist die Listenervariante besser ... zum Einem ersparst Du Dir das notify - da das im Listener (mehr oder weniger) mit drinnen ist ... zum Anderem ist das leichter Erweiterbar ... Du brauchst nur einen neuen Teilnehmer zu implementieren der mit dem Listener umgehen muss ... dadurch wird dem Empfänger kleiner und überschaubarer



> Dumm ist halt, dass es Nachrichten gibt, die allen Teilnehmern zugestellt werden müssen, aber das wär von der Effizient mit beiden Methoden gleich oder?


Effizienz wäre in beiden Fällen ungefähr gleich


----------

