Sobes.tech
Middle+

Fork/Join çerçevesi nedir ve Java'da nasıl kullanılır?

sobes.tech yapay zeka

AI'dan gelen yanıt

Fork/Join çerçevesi, görevleri verimli bir şekilde paralelleştirmek için tasarlanmış, rekürsif olarak daha küçük alt görevlere bölünebilen ve ardından (join) sonuçları birleştirilebilen özel bir Executor çerçevesi uygulamasıdır. "Böl ve yönet" (divide and conquer) ilkesine dayanır.

Ana bileşenler:

  • ForkJoinPool: Görevlerin yürütülmesini yöneten bir iş parçacığı havuzudur. "Work-stealing" mekanizması kullanır; havuzdaki boşta olan iş parçacıkları, meşgul olan diğer iş parçacıklarından görev çalabilir.
  • ForkJoinTask: Bu çerçevede yürütülebilen bir görevi temsil eden soyut sınıftır. İki alt türü vardır:
    • RecursiveAction: Sonuç döndürmeyen görev.
    • RecursiveTask<V>: V türünde sonuç döndüren görev.

Kullanım:

  1. RecursiveAction veya RecursiveTask'tan türeyen bir sınıf oluşturulur.
  2. compute() yöntemi geçersiz kılınır. Bu yöntemde mantık tanımlanır:
    • Görev yeterince küçükse (bir eşik değerinden az), doğrudan yürütülür.
    • Aksi takdirde, görev alt görevlere bölünür ve fork() ile asenkron olarak başlatılır.
    • Alt görevlerin tamamlanması join() ile beklenir ve sonuçlar birleştirilir.
  3. Bir ForkJoinPool örneği oluşturulur.
  4. Görev, invoke() veya submit() kullanılarak havuza gönderilir.

Örnek:

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; // Eşik değeri

    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;
        }
    }
}

// Ana kodda kullanım
// long[] data = new long[10000]; // Başlangıç verileri
// // data doldurulur
// ForkJoinPool pool = new ForkJoinPool();
// long sum = pool.invoke(new SumArrayTask(data, 0, data.length));
// pool.shutdown(); // Kullanımdan sonra havuzu kapat

Avantajlar:

  • Otomatik iş parçacığı havuzu yönetimi.
  • "Work-stealing" sayesinde verimli yük dağılımı.
  • "Böl ve yönet" tipi görevler için geliştirilmiş performans.

Dezavantajlar:

  • Tüm paralel görev türleri için uygun değildir.
  • Basit görevler için diğer yaklaşımlara kıyasla daha karmaşık olabilir.