Sobes.tech
Middle+

Fork/Join çərçivəsi nədir və Java-da necə istifadə olunur?

sobes.tech Süni İntellekt

AI-dan cavab

Fork/Join çərçivəsi — bu, Executor çərçivəsinin ixtisaslaşdırılmış bir tətbiqidir və təkrarlana bilən və daha kiçik alt tapşırıqlara bölünə bilən və sonra nəticələri birləşdirilə bilən tapşırıqları səmərəli şəkildə paralelləşdirmək üçün nəzərdə tutulmuşdur. Bu, "böl və fəth et" prinsipinə əsaslanır.

Əsas komponentlər:

  • ForkJoinPool: Tapşırıqları icra edən işçi hovuzu. Bu, "work-stealing" mexanizmini istifadə edir, burada hovuzdakı boş işləyən işçilər digər məşğul olan işçilərdən tapşırıqları oğurlaya bilərlər.
  • ForkJoinTask: Bu çərçivədə icra oluna bilən tapşırığı təmsil edən abstrakt sinif. İki növü var:
    • RecursiveAction: Nəticə qaytarmayan tapşırıq.
    • RecursiveTask<V>: V tipində nəticə qaytaran tapşırıq.

İstifadə:

  1. RecursiveAction və ya RecursiveTask-ı miras alan sinif yaradılır.
  2. compute() metodu yenidən yazılır. Bu metodda lojiq qeyd olunur:
    • Əgər tapşırıq kifayət qədər kiçikdirsə (müəyyən bir sərhəddən azdırsa), birbaşa icra olunur.
    • Əks halda, tapşırıq alt tapşırıqlara bölünür və fork() metodu ilə asinxron şəkildə icra olunur.
    • Alt tapşırıqların join() metodu ilə tamamlanması gözlənir və nəticələri birləşdirilir.
  3. ForkJoinPool nümunəsi yaradılır.
  4. Tapşırıq invoke() və ya submit() metodları ilə hovuzda təqdim olunur.

Misal:

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; // Sərhəd dəyəri

    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) {
            // Kiçik diapazonlar üçün birbaşa hesablamalar
            long sum = 0;
            for (int i = start; i < end; i++) {
                sum += array[i];
            }
            return sum;
        } else {
            // Tapşırığın bölünməsi
            int mid = start + (end - start) / 2;
            SumArrayTask leftTask = new SumArrayTask(array, start, mid);
            SumArrayTask rightTask = new SumArrayTask(array, mid, end);

            // Alt tapşırıqların asinxron icrası
            leftTask.fork();
            Long rightResult = rightTask.compute();
            Long leftResult = leftTask.join();

            // Nəticələrin birləşdirilməsi
            return leftResult + rightResult;
        }
    }
}

// Əsas kodda istifadə
// long[] data = new long[10000]; // Başlanğıc məlumatlar
// // data doldurulur
// ForkJoinPool pool = new ForkJoinPool();
// long sum = pool.invoke(new SumArrayTask(data, 0, data.length));
// pool.shutdown(); // İstifadədən sonra hovuzu bağla

Üstünlüklər:

  • İşçi hovuzunun avtomatik idarə olunması.
  • Work-stealing sayəsində yükün səmərəli bölünməsi.
  • "Böl və fəth et" tipli tapşırıqlar üçün yaxşı performans.

Çatışmazlıqlar:

  • Bütün paralel tapşırıqlar üçün uyğun deyil.
  • Sadə tapşırıqlar üçün digər yanaşmalara nisbətən daha çətin ola bilər.