Middle+
Co je to framework Fork/Join a jak se používá v Java?
sobes.tech AI
Odpověď od AI
Framework Fork/Join je specializovaná implementace rámce Executor, navržená pro efektivní paralelní rozdělení úkolů, které lze rekurzivně rozdělit na menší podúkoly a poté jejich výsledky sloučit (join). Je založen na principu "dělej a panuj".
Klíčové komponenty:
ForkJoinPool: Pool vláken, který řídí vykonávání úkolů. Používá mechanismus "work-stealing", kde neaktivní vlákna mohou "ukrást" úkoly od jiných zaneprázdněných vláken.ForkJoinTask: Abstraktní třída představující úkol, který může být v tomto rámci vykonán. Má dvě podtřídy:RecursiveAction: Úkol, který nevrací výsledek.RecursiveTask<V>: Úkol, který vrací výsledek typuV.
Použití:
- Vytvoří se třída, která dědí z
RecursiveActionneboRecursiveTask. - Přepíše se metoda
compute(). V této metodě je popsána logika:- Pokud je úkol dostatečně malý (menší než určitá práh), je proveden přímo.
- Jinak je úkol rozdělen na podúkoly, které jsou spuštěny asynchronně metodou
fork(). - Čeká se na dokončení podúkolů metodou
join()a jejich výsledky se sloučí.
- Vytvoří se instance
ForkJoinPool. - Úkol je předán do poolu pomocí metod
invoke()nebosubmit().
Příklad:
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; // Práh
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) {
// Přímý výpočet pro malé rozsahy
long sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return sum;
} else {
// Rozdělení úkolu
int mid = start + (end - start) / 2;
SumArrayTask leftTask = new SumArrayTask(array, start, mid);
SumArrayTask rightTask = new SumArrayTask(array, mid, end);
// Asynchronní spuštění podúkolů
leftTask.fork();
Long rightResult = rightTask.compute();
Long leftResult = leftTask.join();
// Sloučení výsledků
return leftResult + rightResult;
}
}
}
// Použití v hlavním kódu
// long[] data = new long[10000]; // Výchozí data
// // Naplnit data
// ForkJoinPool pool = new ForkJoinPool();
// long sum = pool.invoke(new SumArrayTask(data, 0, data.length));
// pool.shutdown(); // Uzavření poolu po použití
Výhody:
- Automatické řízení poolu vláken.
- Efektivní rozdělení zátěže díky work-stealing.
- Zlepšený výkon pro úkoly typu "dělej a panuj".
Nevýhody:
- Není vhodný pro všechny typy paralelních úkolů.
- Může být složitější na implementaci ve srovnání s jinými přístupy pro jednoduché úkoly.