Threads greifen auf Config-Variablen zu

00d4vid

Mitglied
Ich habe ein Tool, das eine beliebige Anzahl an Threads startet, die alle auf Parameter zugreifen können müssen, die in einer Config-Datei stehen.
Bisher mache ich das so, dass in der Main-Klasse eine Klasse ConfigHandler initialisiert wird, die statische Variablen enthält.
Diese Variablen enthalten als Wert eben das, was in der Config-Datei steht.
Nun wird eine zweite Klasse initialisiert, die ein Webservice ist, über den Threads gestartet werden (also konkret über eine Methode generateFile(), die als @WebMethod deklariert ist).
Jeder gestartete Thread muss möglichst effektiv auf die Werte der Variablen in der ConfigHandler-Klasse zugreifen können.
Geht das grundsätzlich so oder kommen sich die Threads da in die Quere?
Die statischen Variablen werden von den Threads nur gelesen.

Danke im Voraus!
 
Zuletzt bearbeitet:
Hi!

Wenn es nur um Lesezugriffe geht, die Variablen also nie geändert werden, halte ich eine Synchronisation für unnötig. Ich würde dann vorsichtshalber noch ein final einbauen :)

Gruß,

RoCMe
 
Ok. Ich habe nur das Problem, dass die Threads sich irgendwie gegenseitig ausbremsen, zumindest sieht es so aus.
1 Thread braucht ca 30 Sekunden.
Wenn ich 2 starte brauchen beide Threads 60 Sekunden.
Bei vier brauchen alle vier 120 Sekunden usw...

Allerdings habe ich bisher nichts gefunden woher das kommt...
Evtl von dem ConnectionPool zur Datenbank.
Die Threads werden alle per Thread t = new Thread(new Runnable()) aufgerufen, dh. theoretisch müssten sie ja parallel laufen.
 
HRMPF
vergiss die Frage^^
Ich hatte in meinem Connection Pool nur maximal eine physische Verbindung zugelassen und da ich da relativ viele Daten abfragen muss, musste der eine Thread natürlich immer warten, bis der andere mit der Abfrage fertig ist...

Danke für die Hilfe!
 
Hallo ihrs,

ich beschaeftige mich schon die letzten Tage mit Thread handling und ich dachte mir, ich koennte die Frage hier mal posten, um nich zu sehr rumzumuellen.

Ich implementiere gerade ein Tool, das plugins laed und diese ueber separate Threads laufen laesst.
Diese Threads beinhalten Schleifen in der 2 Methoden (zuerst get und danach setWaiting) eines Objektes ParsedModules zugegriffen wird.
Der Haupthtread beinhaltet einen Parser, der nach einem Abschnitt aus einem File immer wieder ne Liste in eben dieselbe Instanz des Objektes reinschieben soll mit der Methode put.
Das parallele Abarbeiten der Plugins durch Threads geschieht deswegen, damit der Parser solange wartet, bis alle (also das langsamste Plugin) fertig sind und soll dann erst weiter machen.

Nun habe ich mir das so vorgestellt. Das ParsedModules hat ne Liste, in dem alle Threads eingetragen werden, die ein Element abgearbeitet haben, quasi ne Warteliste.
Wenn die voll ist, darf der Parser ein neues Element in der Methode put einfuegen und setzt die Warteliste zurueck.
Die get Methode wird von allen Threads aufgerufen und solange die Threads noch nicht in der Warteliste stehen (sonst haetten sie das aktuelle Element schon abgearbeitet), duerfen sie sich das Element nehmen.
Wie gesagt im Thread selber wird get aufgerufen, dann kommt die verarbeitung und dann kommt die setWaiting methode.

Die Klasse ParsedModule sieht so aus:

public class ParsedModules
{
// Parsed modules
private List<HashMap<String, String>> modules;

// Number of threads working with the current modules
private int consumerNumber;

// A list of all threads, working with the new modules
private List<String> consumerThreads = new ArrayList<String>();

private boolean exit = false;

private boolean available = true;

public ParsedModules(HashMap<String, Plugin> plugins)
{
this.consumerNumber = plugins.size();
consumerThreads = new ArrayList<String>(plugins.keySet());
}

/**
* This method waits until the new modules are available and returns them
*
* @return
*/
public synchronized List<HashMap<String, String>> get(String threadName)
{
while (consumerThreads.contains(threadName))
try
{
if (exit)
return null;
wait();
} catch (InterruptedException e)
{
}
notifyAll();
return modules;
}

public synchronized void setWaiting(String threadName)
{
consumerThreads.add(threadName);
notifyAll();
}

/**
* This method waits until the new moduleshave been processed by all plug-ins
*
* @return
*/
public synchronized void put(List<HashMap<String, String>> modules)
{
while (consumerThreads.size() != consumerNumber)
try
{
if (exit)
return;
wait();
} catch (InterruptedException e)
{
}
consumerThreads = new ArrayList<String>();
this.modules = modules;
notifyAll();
}

public synchronized void setExit()
{
this.exit = true;
notifyAll();
}


Das Exit flag is dazu da um spaeter die Threads zu beenden (es kann wohl vorkommen, dass die in der Warteschleife stehen weil sie auf ein neues Element warten, das aber nicht mehr kommt, weil der Parser seine Arbeit beendet hat).

Mein Problem ist nun aber, dass bei groesseren Plugins (im moment mittels Sleep oder Schleifen simuliert) das Programm haengen bleibt.
Ich habe aber keinen schimmer wieso. Und wenn die Plugins weniger komplex sind und das Tool terminiert, stell ich am Ende fest, dass nicht umbedingt jedes Plugin alle Elemente verarbeitet hat (visualisiert durch Threadinterne Zaehler).

Ich habe mir schon die Sachen mit Threadpool und Queue angeschaut, damit kann ich aber wohl nichts anfangen:
Queue ist zu gefaehrlich, da der Parser sehr viele und grosse Dateien durchgeht und in nichmal einer Sekunde 6-7000 Objekte erzeugt, wenn ich die in nen Queue schmeisse und die Plugins (teilweise lahm) den Queue nur halbsoschnell abarbeiten, dann will ich nicht wissen, wie gross der Heapspace sein muesste.
Threadpool macht bei mir keinen Sinn, glaub ich, die Threads fuehren Plugins aus, die wiederum Elemente vom Parser analysieren. Da ist die Reihenfolge der Elemente schon mal wichtig. Da bringt es nichts, wenn ich fuer mehrere Threads nen Pool aufmache und dann ein plugin mit 4 verschiedenen Element gleichzeitg gestartet wird...
 
EDIT: Die "[ j a v a ] Tags sind eine wirklich tolle Erfindung...

Ich habe mir schon die Sachen mit Threadpool und Queue angeschaut, damit kann ich aber wohl nichts anfangen:
Queue ist zu gefaehrlich, da der Parser sehr viele und grosse Dateien durchgeht und in nichmal einer Sekunde 6-7000 Objekte erzeugt, wenn ich die in nen Queue schmeisse und die Plugins (teilweise lahm) den Queue nur halbsoschnell abarbeiten, dann will ich nicht wissen, wie gross der Heapspace sein muesste.
Naja, wenn du immer mehr Objekte erzeugst, als du abarbeiten kannst, fliegt dir das ganze System irgendwann um die Ohren - mit oder ohne Queue!

Meiner Meinung nach wirst du ohne Queue o.Ä. nicht auskommen - eine solche ist doch für genau diese Art von Problemen gedacht. In die Queue wird irgendwas reingeschmissen, beliebig oft und in beliebiger Reihenfolge, und auf der anderen Seite wird das jeweils nächste Element wieder herausgenommen und jedem Plugin zur Bearbeitung vorgelegt. Dann wird gewartet, bis alle Bearbeitungsvorgänge abgeschlossen sind, und dann geht das Spiel von vorne los.

Meiner Meinung nach wirst du um ein solches Verfahren nicht drumrum kommen - irgendwo musst du deine Daten verwahren, bis du sie bearbeiten kannst...
 
Zuletzt bearbeitet:
Danke fuer die schnelle Antwort...

Java-tags,

naja als Gast hab ich da leider keine Legende am Formular, welche Tags moeglich sind, wenn ich noch mehrere Fragen haben sollte, werd ich mich wohl anmelden.

Zu der Sache mit Queue.

Queues sind unmoeglich..da die Reihenfolge der Objekte vom Parser ist wichtig ist fuer die Plugins.
Die Plugins bekommen ja alle das gleiche Element zum Abarbeiten, nur fuehrt jedes seine eigene Analyse damit durch.
Danach werden die Elemente verworfen und die Resultate entsprechend abgespeichert.
Mal abgesehen von den Resultaten, die bei einer gewissen Menge in Dateien ausgelagert werden, kommt es da also zu keinen Speicherproblemen, da ich ausser Resultate nichts sammle.

Ergo waere da ein Queue eine Verschlimmbesserung, selbst, wenn die Daten im Queue in der richtigen Reihenfolge abgearbeitet werden.
Ein Plugin kann manchmal pro geparsten Block ne Sekunde brauchen, in der Haelfte der Zeit hat der Parser eine Datei mit 7000 solcher Bloecke durch. Das wuerde in ein paar Sekunden den Queue sprengen bei unbekannter Anzahl der Dateien. Aus diesem Grund soll der Parser ja auch warten, bis die Plugins fertig sind, dann brauche ich aber auch keinen Queue mehr, da ja immer nur ein Block geparst und analysiert wird.
 
Moin,

Java-tags,
naja als Gast hab ich da leider keine Legende am Formular, welche Tags moeglich sind, wenn ich noch mehrere Fragen haben sollte, werd ich mich wohl anmelden.

dann probiere doch die vorhandenen Button einfach mal aus ..... Du machst nix kaputt - ehrlich :p

Kleiner Tipp weil Ostern ist: nimm' mal den mit '#' und klammere Deinen Code händisch mit [_JAVA]...[_/JAVA] (ohne die Unterstriche) ;)

Gruß
Klaus
 
Danke fuer die schnelle Antwort...
Queues sind unmoeglich..da die Reihenfolge der Objekte vom Parser ist wichtig ist fuer die Plugins.
Und man verwendet eben genau dann eine Queue, wenn die Reihenfolge wichtig ist! Wie an der Kasse beim Einkaufen - hinten anstellen, warten bis man der Reihe ist, und vorne wieder rauspurzeln. Vordrängeln oder Überholen sind theoretisch realisierbar, aber eigentlich nicht im Kern einer Standard-Queue enthalten!

Die Plugins bekommen ja alle das gleiche Element zum Abarbeiten, nur fuehrt jedes seine eigene Analyse damit durch.
Danach werden die Elemente verworfen und die Resultate entsprechend abgespeichert.
Bekommen nun alle Plugins EIN Element oder mehrere? Ist aber auch egal, das Prinzip bleibt nach wie vor das, wie ich es oben beschrieben habe: Element(e) aus der Queue holen, parallel von allen Plugins verarbeiten lassen, wenn alle fertig sind Ergebnisse speichern und Elemente verwerfen, dann nächste(s) Elemen(e).

Ergo waere da ein Queue eine Verschlimmbesserung, selbst, wenn die Daten im Queue in der richtigen Reihenfolge abgearbeitet werden.
Ein Plugin kann manchmal pro geparsten Block ne Sekunde brauchen, in der Haelfte der Zeit hat der Parser eine Datei mit 7000 solcher Bloecke durch. Das wuerde in ein paar Sekunden den Queue sprengen bei unbekannter Anzahl der Dateien. Aus diesem Grund soll der Parser ja auch warten, bis die Plugins fertig sind, dann brauche ich aber auch keinen Queue mehr, da ja immer nur ein Block geparst und analysiert wird.

Das ändert alles! Bis hierhin war mir nicht klar, dass du dem Parser sagen kannst, dass du gerne das nächste Objekt hättest. Ich bin davon ausgegangen, dass du irgendwelche Realtime Daten oder sonstwas bekommst, bis zu 7000 je Sekunde, und diese gerne abarbeiten möchtest.
Wenn der Parser natürlich mit dem nächsten Element warten kann, bis alle Plugins fertig sind, ist die Queue ja praktisch schon im Parser drin, also wirklich überflüssig! Dann sehe ich aber das Problem gar nicht mehr.

Code:
while (Parser.hasElements()) {
element = parser.next();
foreach Plugin {
handleElement;
}
foreach Plugin {
Plugin.getResult;
}}

So im Prinzip. Oder habe ich jetzt irgendwas falsch verstanden?
 
@VFL
Danke fuer den nett gemeinten Ratschlag,

ich bin mir durchaus die Funktionalitaeten diverser Knoepfe in Formularen bewussst. Nur kann ich die Knoepfe nur dann benutzen, wenn sie vorhanden sind.
Hier als Gast sehe ich (zumindest im Firefox) nur die Knoepfe Antworten und Vorschau, mehr nicht.

@RoCMe,

das mit dem Parser und dem Queue siehst du richtig...natuerlich waere es im Prinzip netter, wenn der Parser einfach loslegen kann und alles in nem Queue schmeisst und die Plugins sich davon bedienen, war auch mein erster Entwurf.
Da wir aber in Zukunft nicht wissen, wer was fuer Plugins implementiert und was die so alles machen (evtl werden dann noch die Daten mit Daten aus anderen Netzen verglichen etc) wuerden solche Prozesse sehr lange dauern und was dann passiert hab ich ja schon beschrieben.

Deine Zusammenfassung des Prozessablaufs passt ganz gut...nur gibt es kein foreach plugin teil. ich schreibe das mal so (hoffentlich tuns die tags auch ;) )

Java:
while (Parser.hasElements()) {
        element = parser.next();
        // Fuege element zu consumner/producer-objekt, wenn da noch nich alle threads auf neuen input warten, wartet der parser hier quasi durch das wait in der put methode
        parsedModules.put(element);
}

//dann irgendwo am ende des programms:
foreach Plugin {
       Plugin.getResult;
}
 
Zuletzt bearbeitet von einem Moderator:
Zurück