pp.12.01-ForkJoinArrayFilter
in-situ Filterung als divide and conquer
- Projekt:
pp.12.01-ForkJoinArrayFilter
- Bearbeitungszeit: 25 Minuten
- Musterlösung: 15 Minuten
- Kompatibilität: mindestens Java SE 10
- Das Fork-Join Framework eignet sich besonders gut zur Implementierung von Array-Algorithmen.
- Alle Werte eines Arrays mit
MAX
überschreiben, die >MAX
sind. - Das Array soll halbiert werden, bis \(\le\) 4 Elemente übrig sind, wie in folgendem Schaubild:
Quellcode von pp.FilterTask
public class FilterTask extends RecursiveAction {
private static final int ARRAY_LEN = 16;
private static final int SLICE_LEN = 4;
private static final int MAX = 10;
private static int instanceCounter = 0;
private final ArrayList<Integer> array;
private final int start;
private final int end;
FilterTask(ArrayList<Integer> array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
synchronized(FilterTask.class) {
FilterTask.instanceCounter++;
}
}
@Override
protected void compute() {
// Fallunterscheidung einführen, die prüft, ob weiter rekursiv halbiert
// werden muss oder ob nun der Rekursionsanker erreicht ist
// Rekursionsanker: über Array-Elemente mit einer for-Schleife iterieren
// und Filter-Aktion anwenden (muss noch implementiert werden)
// Array in zwei Hälften aufteilen und beide Hälften rekursiv behandeln:
var mid = this.start + ((this.end - this.start) / 2);
var left = new FilterTask(this.array, this.start, mid);
var right = new FilterTask(this.array, mid, this.end);
left.fork();
right.fork();
right.join();
left.join();
}
public static void main(String... args) {
// Array initialisieren
// initialen FilterTask erzeugen und
// FilterTask im *Common Thread Pool* starten:
// ForkJoinPool.commonPool().invoke(...);
// auf das Ende warten
// gefiltertes Array ausgeben
}
}
Aufgaben
- Vervollständigen Sie die Methode
compute
:- führen Sie eine neue Fallunterscheidung ein, die prüft, ob weiter rekursiv halbiert werden muss oder ob nun der Rekursionsanker erreicht ist (das Array soll halbiert werden, bis \(\le\) 4 Elemente übrig sind).
- implementieren Sie die Aktion für den Rekursionsanker: Iterieren Sie dazu mit einer
for
-Schleife über die Array-Elemente und wenden Sie auf jedes Element die Filter-Aktion an (Element mitMAX
überschreiben, falls Element \(>\)MAX
ist.)
- Schreiben Sie ein Hauptprogramm, mit dem Sie den
FilterTask
im Common Thread Pool ausprobieren. - Wie oft wird bei einem Array mit \(n\) Elementen geforkt?
Literatur
Hettel, Jörg und Manh Tien Tran. 2016. Nebenläufige Programmierung mit Java. Konzepte und Programmiermodelle für Multicore-Systeme. Heildelberg: dpunkt.verlag.