public class Map { public static void map(Fun f, T[] a, R[] b, int n) throws InterruptedException { if (a == null || b == null || f == null) throw new IllegalArgumentException("a, b und f dürfen nicht null sein"); if (n <= 0) throw new IllegalArgumentException("Anzahl Bereiche (n) muss mind. 1 sein, war " + n); if (a.length != b.length) throw new IllegalArgumentException("Die Arrays müssen dieselbe Länge haben"); int k = a.length; // Umbenennung wie Aufgabenstellung Thread t[] = new Thread[n]; // hier werden alle Threads gespeichert /* FALLS DU DIE LÖSUNG HIER NICHT VERSTEHST, SCHAU DIR DIE LÖSUNG IN DER METHODE mapSimple AN! */ for (int i = 0; i < n; i++) { final int from, length; if (i < k%n) { // das sind die "normalen k%n vielen Bereiche" length = (int)(k/n)+1; // der Größe |_k/n_|+1 from = i*length; // from = Beginn im Array a für aktuellen Thread } else { // die übrigen Bereiche (bei from zusätzlich +1 "nachholen") length = (int)(k/n); from = i*length + (k%n)*1; } t[i] = new Thread( new Runnable() { @Override public void run() { for (int j = 0; j < length; j++) b[from+j] = f.apply(a[from+j]); } } ); t[i].start(); } // auf alle warten for (Thread t1 : t) t1.join(); } public static void main(String[] args) { // Testen: IntToString f = new IntToString(); // die auf a anzuwendende Funktion Integer[] a = new Integer[]{1, null, 4, 6}; // wird konvertiert (-> T) String[] b = new String[a.length]; // Ergebnisse (-> R) int n = 5; try { map(f, a, b, n); System.out.println(java.util.Arrays.toString(a) + " wurde zu "); System.out.println(java.util.Arrays.toString(b)); } catch (InterruptedException e) { System.out.println("Unterbrochen..."); } } /** * Alternative zu map, falls map unverständlich sein sollte. */ public static void mapSimple(Fun f, T[] a, R[] b, int n) throws InterruptedException { if (a == null || b == null || f == null) throw new NullPointerException("a, b und f dürfen nicht null sein"); if (a.length != b.length) throw new IllegalArgumentException("Die Arrays müssen dieselbe Länge haben"); if (n <= 0) throw new IllegalArgumentException("Anzahl Bereiche (n) muss mind. 1 sein, war " + n); int k = a.length; // Umbenennung wie Aufgabenstellung Thread t[] = new Thread[n]; // hier werden alle Threads gespeichert int threadsNormal = k%n; // - k%n viele Bereiche int lengthNormal = (int)(k/n)+1; // der Größe |_k/n_|+1 int threadsOther = n-threadsNormal; // - restliche Bereiche int lengthOther = (int)(k/n); // haben die Größe |_k/n_| // alternativ zu den nun folgenden Aufrufen von createThread könnte // man natürlich eine weitere Klasse für Runnables oder Threads schreiben // Threads für normale Bereiche erzeugen for (int i = 0; i < threadsNormal; i++) { int from = i*lengthNormal; int to = from+lengthNormal; t[i] = createThread(f, a, b, from, to); } // Threads für übrige Bereiche erzeugen for (int i = 0; i < threadsOther; i++) { int from = threadsNormal*lengthNormal+i*lengthOther; int to = from+lengthOther; t[threadsNormal+i] = createThread(f, a, b, from, to); } // alle starten for (int i = 0; i < t.length; i++) { t[i].start(); } // auf alle warten for (int i = 0; i < t.length; i++) { t[i].join(); } } /** * Erzeugt einen Thread, der (wenn er gestartet wird) die Funktion f auf * alle Elemente von from (inkl.) bis to (exkl.) des Arrays a anwendet * und die Ergebnisse im gleichen Bereich des Arrays b speichert. * @return den erzeugten Thread */ private static Thread createThread(Fun f, T[] a, R[] b, int from, int to) { System.out.println("Thread für den Bereich von " + from + " bis " + (to-1) + "."); if (from >= to) System.out.println(" -> Dieser Thread tut also nichts."); return new Thread( new Runnable() { @Override public void run() { for (int i = from; i < to; i++) { b[i] = f.apply(a[i]); } } } ); } }