Middle+
383
Šta je Fork/Join okvir i kako se koristi u Javi?
Одговор од АИ
sobes.tech АИ
Fork/Join okvir je specijalizovana implementacija okvira Executor, namenjena za efikasno paralelno razbijanje zadataka koji se mogu rekurzivno razbiti na manje podzadatke, a zatim spojiti (join) njihove rezultate. Osnovan je na principu "podeli i osvoji".
Ključne komponente:
ForkJoinPool: Bazen niti koji upravlja izvršavanjem zadataka. Koristi mehanizam "work-stealing", gde neaktivne niti mogu "ukrasti" zadatke od drugih zauzetih niti.ForkJoinTask: Apstraktna klasa koja predstavlja zadatak koji se može izvršiti u ovom okviru. Ima dve podklase:RecursiveAction: Zadatak koji ne vraća rezultat.RecursiveTask<V>: Zadatak koji vraća rezultat tipaV.
Upotreba:
- Kreira se klasa koja nasleđuje
RecursiveActioniliRecursiveTask. - Prepisuje se metoda
compute(). U ovoj metodi se opisuje logika:- Ako je zadatak dovoljno mali (manji od određenog praga), izvršava se direktno.
- U suprotnom, zadatak se razbija na podzadatke koji se pokreću asinhrono metodom
fork(). - Čeka se završetak podzadatka metodom
join()i njihovi rezultati se spajaju.
- Kreira se instanca
ForkJoinPool. - Zadatak se predaje u bazen koristeći
invoke()ilisubmit().
Primer:
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) {
// Direktno računanje za male opsege
long sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return sum;
} else {
// Podela zadatka
int mid = start + (end - start) / 2;
SumArrayTask leftTask = new SumArrayTask(array, start, mid);
SumArrayTask rightTask = new SumArrayTask(array, mid, end);
// Asinhrono izvršavanje podzadatka
leftTask.fork();
Long rightResult = rightTask.compute();
Long leftResult = leftTask.join();
// Spajanje rezultata
return leftResult + rightResult;
}
}
}
// Upotreba u glavnom kodu
// long[] data = new long[10000]; // Početni podaci
// // Popunjavanje podataka
// ForkJoinPool pool = new ForkJoinPool();
// long sum = pool.invoke(new SumArrayTask(data, 0, data.length));
// pool.shutdown(); // Zatvaranje bazena nakon upotrebe
Prednosti:
- Automatsko upravljanje bazenom niti.
- Efikasno raspoređivanje opterećenja zahvaljujući work-stealing-u.
- Poboljšana performansa za zadatke tipa "podeli i osvoji".
Nedostaci:
- Nije pogodan za sve tipove paralelnih zadataka.
- Može biti složeniji za implementaciju u poređenju sa drugim pristupima za jednostavne zadatke.