Java Eşzamanlılığı - Fork-Join çerçevesi

Çatallı birleştirme çerçevesi, belirli bir görevi birkaç çalışanın kırmasına ve ardından sonucun bunları birleştirmesini beklemeye izin verir. Çok işlemcili makinenin kapasitesini büyük ölçüde kullanır. Çatallı birleştirme çerçevesinde kullanılan temel kavramlar ve nesneler aşağıdadır.

Çatal

Çatal, bir görevin kendisini eşzamanlı olarak yürütülebilen daha küçük ve bağımsız alt görevlere ayırdığı bir süreçtir.

Sözdizimi

Sum left  = new Sum(array, low, mid);
left.fork();

Burada Sum, RecursiveTask'ın bir alt sınıfıdır ve left.fork () görevi alt görevlere ayırır.

Katılmak

Birleştirme, alt görevlerin yürütülmesi bittikten sonra görevin alt görevlerin tüm sonuçlarına katıldığı, aksi takdirde beklemeye devam ettiği bir süreçtir.

Sözdizimi

left.join();

Solda Sum sınıfının bir nesnesi var.

ForkJoinHavuzu

çatal-birleştir görev bölme ile çalışmak üzere tasarlanmış özel bir iş parçacığı havuzudur.

Sözdizimi

ForkJoinPool forkJoinPool = new ForkJoinPool(4);

Burada 4 CPU'luk paralellik seviyesine sahip yeni bir ForkJoinPool.

RecursiveAction

RecursiveAction, herhangi bir değer döndürmeyen bir görevi temsil eder.

Sözdizimi

class Writer extends RecursiveAction {
   @Override
   protected void compute() { }
}

YinelemeliGörev

RecursiveTask, bir değer döndüren bir görevi temsil eder.

Sözdizimi

class Sum extends RecursiveTask<Long> {
   @Override
   protected Long compute() { return null; }
}

Misal

Aşağıdaki TestThread programı, iş parçacığı tabanlı ortamda Fork-Join çerçevesinin kullanımını gösterir.

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class TestThread {

   public static void main(final String[] arguments) throws InterruptedException, 
      ExecutionException {
      
      int nThreads = Runtime.getRuntime().availableProcessors();
      System.out.println(nThreads);
      
      int[] numbers = new int[1000]; 

      for(int i = 0; i < numbers.length; i++) {
         numbers[i] = i;
      }

      ForkJoinPool forkJoinPool = new ForkJoinPool(nThreads);
      Long result = forkJoinPool.invoke(new Sum(numbers,0,numbers.length));
      System.out.println(result);
   }  

   static class Sum extends RecursiveTask<Long> {
      int low;
      int high;
      int[] array;

      Sum(int[] array, int low, int high) {
         this.array = array;
         this.low   = low;
         this.high  = high;
      }

      protected Long compute() {
         
         if(high - low <= 10) {
            long sum = 0;
            
            for(int i = low; i < high; ++i) 
               sum += array[i];
               return sum;
         } else {	    	
            int mid = low + (high - low) / 2;
            Sum left  = new Sum(array, low, mid);
            Sum right = new Sum(array, mid, high);
            left.fork();
            long rightResult = right.compute();
            long leftResult  = left.join();
            return leftResult + rightResult;
         }
      }
   }
}

Bu, aşağıdaki sonucu verecektir.

Çıktı

32
499500