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