tutorials.de Buch-Aktion 05/2012
ERLEDIGT
NEIN
ANTWORTEN
14
ZUGRIFFE
348
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    00d4vid 00d4vid ist offline Mitglied Silber
    Registriert seit
    Nov 2007
    Ort
    München
    Beiträge
    51
    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!
    Geändert von 00d4vid (29.03.10 um 13:02 Uhr)
     
    Hallo Nuray!

  2. #2
    RoCMe RoCMe ist offline Mitglied Gold
    Registriert seit
    Dec 2007
    Beiträge
    193
    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
     

  3. #3
    00d4vid 00d4vid ist offline Mitglied Silber
    Registriert seit
    Nov 2007
    Ort
    München
    Beiträge
    51
    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.
     
    Hallo Nuray!

  4. #4
    00d4vid 00d4vid ist offline Mitglied Silber
    Registriert seit
    Nov 2007
    Ort
    München
    Beiträge
    51
    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 Nuray!

  5. #5
    derSchmu Tutorials.de Gastzugang
    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...
     

  6. #6
    RoCMe RoCMe ist offline Mitglied Gold
    Registriert seit
    Dec 2007
    Beiträge
    193
    EDIT: Die "[ j a v a ] Tags sind eine wirklich tolle Erfindung...

    Zitat Zitat von derSchmu Beitrag anzeigen
    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...
    Geändert von RoCMe (01.04.10 um 13:44 Uhr)
     

  7. #7
    derSchmu Tutorials.de Gastzugang
    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.
     

  8. #8
    Avatar von vfl_freak
    vfl_freak vfl_freak ist offline Mitglied Diamant
    Registriert seit
    Aug 2007
    Ort
    Niedersachsen
    Beiträge
    2.161
    Moin,

    Zitat Zitat von derSchmu Beitrag anzeigen
    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

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

    Gruß
    Klaus
     
    Es ist noch kein Meister vom Himmel gefallen - sonst hätte man schon längst seine Leiche gefunden !!

    Falls ich helfen konnte, wäre eine Bewertung oder ein Danke nett ;-)
    -------------------------------------------------------------------------------------------------
    Ich beantworte keine Fragen per PN !!
    Stellt Eure Fragen im Forum - dann haben alle etwas davon !!

  9. #9
    RoCMe RoCMe ist offline Mitglied Gold
    Registriert seit
    Dec 2007
    Beiträge
    193
    Zitat Zitat von derSchmu Beitrag anzeigen
    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 :
    1
    2
    3
    4
    5
    6
    7
    8
    
    while (Parser.hasElements()) {
    element = parser.next();
    foreach Plugin {
    handleElement;
    }
    foreach Plugin {
    Plugin.getResult;
    }}

    So im Prinzip. Oder habe ich jetzt irgendwas falsch verstanden?
     

  10. #10
    derSchmu Tutorials.de Gastzugang
    @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 )

    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    
    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;
    }
     

  11. #11
    Avatar von vfl_freak
    vfl_freak vfl_freak ist offline Mitglied Diamant
    Registriert seit
    Aug 2007
    Ort
    Niedersachsen
    Beiträge
    2.161
    Moin,

    Zitat Zitat von derSchmu Beitrag anzeigen
    @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.
    Oh bitte ... gerne

    Aber dann gilt immer noch :
    klammere Deinen Code händisch mit [_JAVA]...[_/JAVA] (ohne die Unterstriche)

    Gruß
    Klaus
     
    Es ist noch kein Meister vom Himmel gefallen - sonst hätte man schon längst seine Leiche gefunden !!

    Falls ich helfen konnte, wäre eine Bewertung oder ein Danke nett ;-)
    -------------------------------------------------------------------------------------------------
    Ich beantworte keine Fragen per PN !!
    Stellt Eure Fragen im Forum - dann haben alle etwas davon !!

  12. #12
    derSchmu Tutorials.de Gastzugang
    Hallo ihrs und frohe Ostern gehabt zu haben.

    So, ich habe nun nochmal mein Threadhandling ueberprueft und nachdem ich die Values verglichen habe, wie viele Elemente mit der put Methode uebergeben werden und wie viele mit der get Methode von jedem Thread entnommen werden, habe ich festgesellt, dass das Thread handling an und fuer sich einwandfrei laeuft, es werden alle entsprechenden Werte uebergeben und die Plugins arbeiten auch mit allen erzeugten Werten.

    Nun bin ich dabei auf das Problem gestossen, dass hier und da die Hashmaps in bestimmten Plugin Instanzen nicht mehr komplett sind. Da diese Maps aber von einem Parser im Kern erstellt werden und die Elemente die fehlen zu Fehlermeldungen im Parser fuehren wuerden, kann ich von der Seite sagen, dass der Parser alle Elemente zur Verfuegung stellt.

    Nun habe ich ein wenig Google benutzt und bin dabei auf die Problematik gestossen, dass Hashmaps nicht umbedingt Threadsafe sind.
    Meine Threads bekommen aus der im letzten Kommentar von mir abgebildeten Klasse die Liste von Hashmaps wobei in jedem Thread ueber die Liste iteriert wird und fuer jede Map das Plugin (im selben Thread) ausgefuehrt wird.

    Nundenn, wenn die in der Liste enthaltenen Hashmaps Threadseitig das Problem sind (die Liste an und fuer sich kommt ja komplett an, da die Groesse der geschickten Listen korrekt in den Plugins/Threads registriert wird) und mir die Elemente der Hashmaps beim Lesezugriff (keine andere Art ist in den Plugins vorhanden) floeten gehen, muesste ich dann ja 'einfach' die Hashmaps durch eine Threadsichere Datenstruktur ersetzen, welche dann (da die Plugins ueber ein Interface definiert sind, welches von einer Map ausgeht) in den einzelnen Threads in eine solche Hashmap zurueckverwandeln...oder?
     

  13. #13
    RoCMe RoCMe ist offline Mitglied Gold
    Registriert seit
    Dec 2007
    Beiträge
    193
    Hi!

    Ich hab mir jetzt nicht genau angesehen, wo das Problem liegt, aber synchronisierte HashMaps bekommst du so:

    z.B. so:
    Code java:
    1
    
    Hashmap objHashmap = Collections.synchronizedMap(new HashMap(....));

    Oder aber du verwendest eine Hashtable, die ist schon von Haus aus thread safe!

    mfg,

    RoCMe
     

  14. #14
    derSchmu Tutorials.de Gastzugang
    Hallo und guten Morgen auch,

    danke fuer die zuegige Antwort.

    Ich habe es mal mit den Hashtables probiert. Die wandle ich dann in jedem Thread in eine lokale Hashmap um (Im Moment mach ich das nur, indem ich ueber die einzelnen Elemente der Table iteriere und die dann in die Map schmeisse, finde im Moment keine schnellere Loesung). Diese lokale Map wird dann an jedes Plugin in einem Thread weitergegeben.
    Dabei habe ich zunaechst eine concurrentModificationException bekommen (wohl klar, waehrend ein Thread auf die Table aus dem parsedModules Objekt zugreift und ein anderer Thread will ebenso verfahren, dann gehts ersmal in die Hose), die Excpetion habe ich nun aber umgangen, indem in ich diese Konvertierung der Table in einem synchronized (parsedModules) Block geschrieben habe.

    Und siehe da, ich hab das Tool nun mehrere Male mit hunderten von Dateien ausprobiert und anscheinend sind auch nun die Maps wieder komplett.
    Ich werd aber deinen Tipp mit der synchronized Map nochmal ausprobieren, das wuerde mir evtl die Konvertierung ersparen und wahrscheinlich auch den zusaetzlichen synchronized Block..
     

  15. #15
    derSchmu Tutorials.de Gastzugang
    Hallo nochmals,

    hier ein kurzes Update:

    Ich habe jetzt mal mit Collections.synchronizedMap die Sache ausprobiert.
    Funktioniert auch super, die Vorteile:
    Kein zusaetzlicher synchronized Block im Thread noetig.
    Konvertierung von Map nach HashMap ueber putAll kein Problem.

    Wie schon gesagt, eine Konvertierung war noch noetig, da ich der synchronizedMap zwar ne Hashmap uebergeben kann, die aber als Typ Map instanziiert wird/werden muss.

    Code java:
    1
    2
    3
    4
    5
    
    // Type mismatch: cannot convert from Map to HashMap
    HashMap<String, String> resultCdr = Collections.synchronizedMap(new HashMap<String, String>());
     
    //Moeglich
    Map<String, String> resultCdr = Collections.synchronizedMap(new HashMap<String, String>());
     

Ähnliche Themen

  1. Setzen von Config-Variablen zur Laufzeit auf JEE5-Server
    Von mcdroemmel im Forum Enterprise Java (JEE, J2EE, Spring & Co.)
    Antworten: 2
    Letzter Beitrag: 18.03.09, 11:07
  2. Variablen in Config.php ändern?
    Von LittleDestroyer im Forum PHP
    Antworten: 12
    Letzter Beitrag: 26.08.08, 04:50
  3. Antworten: 6
    Letzter Beitrag: 24.11.05, 13:56
  4. Warum immer config.inc.php und nicht einfach config.php
    Von Templorials im Forum Coders Talk
    Antworten: 2
    Letzter Beitrag: 01.09.04, 18:18
  5. config.php variablen
    Von nordi im Forum PHP
    Antworten: 3
    Letzter Beitrag: 16.09.02, 20:36