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...