Hallo, ich hoffe, ihr könnt mir mal wieder helfen.
Oder mir sagen, ob ich auf dem Holzweg bin
Und zwar habe ich ein Bildbearbeitungsprogramm, das ein Mosaikbild erstellen soll.
Langsam und sequentiell ist das auch kein Problem.
Allerdings soll es jetzt parallel werden, mit einer begrenzten, aber variablen (heisst, ich möchte es auf einen Knopfdruck ändern können) Anzahl an Threads.
Mein erster Ansatz war, dass ich jeden einzelnen Bearbeitungspunkt (Anzahl der "Unterbilder" bestimmen, Durchschnittsfarbwerte aller Unterbilder bestimmen, für jedes Unterbild das passende Ersatzbild finden und entsprechend zu verkleinern) eine beliebige (für den Anfang erstmal entsprechend der Anzahl der Unterbilder) Anzahl an Threads laufen habe lassen. Am Ende von jedem Bearbeitunspunkt wurde mit einem join() gewartet, bis alle Threads fertig sind und weiter zum nächsten Bearbeitungspunkt.
Dass das wohl zu einfach gedacht war, ist mir bewusst, aber so dauert die Berechnung sogar 3 Sekunden länger als bei der sequentiellen Berechnung.
Jetzt die eigentliche Frage:
Ich möchte mit der Auswertung der Durchschnittswerte anfangen und bei jedem fertig erstellten Wert das entsprechende Unterbild weiterreichen, um es ersetzen zu lassen.
Also im Prinzip Producer und Consument.
Daher die Idee, einen Pool zu erstellen mit x möglichen Threads.
Die Klasse, die meinen Durchschnittswert erstellt, würde ich Callable implementieren lassen, damit das Ergebnis der Berechnung an den Pool weitergereicht wird.
Dazu gibt es noch eine Klasse, die von Runnable abgeleitet ist, die dann alle Ergebnisse auffängt und weiterverarbeitet.
So wie ich das aber bisher habe, wird immer erst die ganze Liste von Callable abgearbeitet, bis Runnable rangelassen wird.
Codeschnipsel:
// berechne Durchschnittsfarbwert von BufferedImage
Wie bekomme ich das jetzt dazu, dass MyRunnable aufgerufen wird, sobald das erste Ergebnis vorhanden ist? (notify()?, aber wie?)
Ist es überhaupt sinnvoll, verschiedene Bearbeitungsschritte gleichzeitig loslaufen zu lassen?
Mein erster Gedanke wäre gewesen, die einzelnen Bearbeitungen möglichst schnell laufen zu lassen, da bis zu 10.000 Unterbilder entstehen können.
Aber wie eingangs gesagt: Aus irgendeinem Grund ist da die sequentielle Verarbeitung bei mir schneller...
Oder mir sagen, ob ich auf dem Holzweg bin
Und zwar habe ich ein Bildbearbeitungsprogramm, das ein Mosaikbild erstellen soll.
Langsam und sequentiell ist das auch kein Problem.
Allerdings soll es jetzt parallel werden, mit einer begrenzten, aber variablen (heisst, ich möchte es auf einen Knopfdruck ändern können) Anzahl an Threads.
Mein erster Ansatz war, dass ich jeden einzelnen Bearbeitungspunkt (Anzahl der "Unterbilder" bestimmen, Durchschnittsfarbwerte aller Unterbilder bestimmen, für jedes Unterbild das passende Ersatzbild finden und entsprechend zu verkleinern) eine beliebige (für den Anfang erstmal entsprechend der Anzahl der Unterbilder) Anzahl an Threads laufen habe lassen. Am Ende von jedem Bearbeitunspunkt wurde mit einem join() gewartet, bis alle Threads fertig sind und weiter zum nächsten Bearbeitungspunkt.
Dass das wohl zu einfach gedacht war, ist mir bewusst, aber so dauert die Berechnung sogar 3 Sekunden länger als bei der sequentiellen Berechnung.
Jetzt die eigentliche Frage:
Ich möchte mit der Auswertung der Durchschnittswerte anfangen und bei jedem fertig erstellten Wert das entsprechende Unterbild weiterreichen, um es ersetzen zu lassen.
Also im Prinzip Producer und Consument.
Daher die Idee, einen Pool zu erstellen mit x möglichen Threads.
Die Klasse, die meinen Durchschnittswert erstellt, würde ich Callable implementieren lassen, damit das Ergebnis der Berechnung an den Pool weitergereicht wird.
Dazu gibt es noch eine Klasse, die von Runnable abgeleitet ist, die dann alle Ergebnisse auffängt und weiterverarbeitet.
So wie ich das aber bisher habe, wird immer erst die ganze Liste von Callable abgearbeitet, bis Runnable rangelassen wird.
Codeschnipsel:
// berechne Durchschnittsfarbwert von BufferedImage
Java:
class MyCallable implements Callable<String> {
private BufferedImage buffIm;
private int jobnummer;
MyCallable(BufferedImage b, int jobnummer) {
this.buffIm = b;
this.jobnummer = jobnummer;
}
public String call() {
System.out.println("Nr: " + jobnummer + " es wird gearbeitet! " );
//mach viel Zeugs und berechne den durchschnittlichen Farbwert vom Bild
return averageRgb.toString() + " erstellt von Jobnummer: " + jobnummer;
}
}
Set<MyCallable> callables = new HashSet<MyCallable>();
for (BufferedImage image : buffImages) {
MyCallable c = new MyCallable(image, buffImages.indexOf(image));
callables.add(c);
}
// es sollen nur drei Threads parallel laufen
ExecutorService executor = Executors.newFixedThreadPool(3);
/**
*
*/
List<Future<String>> result = executor.invokeAll(callables);
/**
* soll später ein Bild finden, dass dem (noch nicht) übergebenen entspricht.
*/
class MyRunnable implements Runnable {
String bs;
public MyRunnable(Future<String> future)
throws InterruptedException, ExecutionException,
TimeoutException {
bs = future.get(2, TimeUnit.SECONDS);
}
public void run() {
System.out.println("Soeben traf diese Meldung ein: " + bs);
}
}
/**
* hier wird der lesethread aufgerufen.
*/
for (Future<String> future : result) {
MyRunnable my = new MyRunnable(future);
Thread thread = new Thread(my);
thread.start();
}
executor.shutdown();
}
}
Wie bekomme ich das jetzt dazu, dass MyRunnable aufgerufen wird, sobald das erste Ergebnis vorhanden ist? (notify()?, aber wie?)
Ist es überhaupt sinnvoll, verschiedene Bearbeitungsschritte gleichzeitig loslaufen zu lassen?
Mein erster Gedanke wäre gewesen, die einzelnen Bearbeitungen möglichst schnell laufen zu lassen, da bis zu 10.000 Unterbilder entstehen können.
Aber wie eingangs gesagt: Aus irgendeinem Grund ist da die sequentielle Verarbeitung bei mir schneller...