Middle+
Ce este framework-ul Fork/Join și cum este utilizat în Java?
sobes.tech AI
Răspuns de la AI
Framework-ul Fork/Join este o implementare specializată a framework-ului Executor, proiectată pentru paralelizarea eficientă a sarcinilor care pot fi împărțite recursiv în sub-sarcini mai mici și apoi unite (join) rezultatele lor. Se bazează pe principiul "divide și cucerește" (divide and conquer).
Componente cheie:
ForkJoinPool: Un pool de fire de execuție care gestionează executarea sarcinilor. Utilizează un mecanism de "work-stealing", în care firele inactive din pool pot "fura" sarcini de la alte fire ocupate.ForkJoinTask: Clasă abstractă care reprezintă o sarcină ce poate fi executată în acest framework. Are două subtipuri:RecursiveAction: Sarcină care nu returnează rezultat.RecursiveTask<V>: Sarcină care returnează un rezultat de tipV.
Utilizare:
- Se creează o clasă care moștenește de la
RecursiveActionsauRecursiveTask. - Se suprascrie metoda
compute(). În această metodă se descrie logica:- Dacă sarcina este suficient de mică (mai mică decât un prag), se execută direct.
- În caz contrar, sarcina se împarte în sub-sarcini, care sunt executate asincron prin
fork(). - Se așteaptă finalizarea sub-sarcinilor cu
join()și se combină rezultatele.
- Se creează o instanță de
ForkJoinPool. - Sarcina este trimisă în pool folosind
invoke()sausubmit().
Exemplu:
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ForkJoinPool;
class SumArrayTask extends RecursiveTask<Long> {
private final long[] array;
private final int start;
private final int end;
private static final int THRESHOLD = 1000; // Prag
public SumArrayTask(long[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
if (end - start <= THRESHOLD) {
long sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return sum;
} else {
int mid = start + (end - start) / 2;
SumArrayTask leftTask = new SumArrayTask(array, start, mid);
SumArrayTask rightTask = new SumArrayTask(array, mid, end);
leftTask.fork();
Long rightResult = rightTask.compute();
Long leftResult = leftTask.join();
return leftResult + rightResult;
}
}
}
// Utilizare în codul principal
// long[] data = new long[10000]; // Date de intrare
// // Umpleți datele
// ForkJoinPool pool = new ForkJoinPool();
// long sum = pool.invoke(new SumArrayTask(data, 0, data.length));
// pool.shutdown(); // Închideți pool-ul după utilizare
Avantaje:
- Management automat al pool-ului de fire.
- Distribuție eficientă a sarcinii datorită "work-stealing".
- Performanță îmbunătățită pentru sarcini de tip "divide and conquer".
Dezavantaje:
- Nu este potrivit pentru toate tipurile de sarcini paralele.
- Poate fi mai dificil de implementat comparativ cu alte abordări pentru sarcini simple.