Java Fork/Join Framework-Beispiele

Beispiele für Java Fork / Join Framework

What is Fork/Join?
Lesen Sie dieseJava Fork/Join paper by Doug Lea

Das Fork / Join-Framework ist seit Java 7 verfügbar, um das Schreiben paralleler Programme zu vereinfachen. Wir können das Fork / Join-Framework implementieren, indem wir entwederRecursiveTask oderRecursiveAction erweitern

1. Fork/Join – RecursiveTask

Ein Fork-Join-Beispiel zum Summieren aller Zahlen aus einem Bereich.

ForkJoinAdd.java

package com.example.concurrency.forkjoin;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.stream.LongStream;

public class ForkJoinAdd extends RecursiveTask {

    private final long[] numbers;
    private final int start;
    private final int end;
    public static final long threshold = 10_000;

    public ForkJoinAdd(long[] numbers) {
        this(numbers, 0, numbers.length);
    }

    private ForkJoinAdd(long[] numbers, int start, int end) {
        this.numbers = numbers;
        this.start = start;
        this.end = end;
    }

    @Override
    protected Long compute() {

        int length = end - start;
        if (length <= threshold) {
            return add();
        }

        ForkJoinAdd firstTask = new ForkJoinAdd(numbers, start, start + length / 2);
        firstTask.fork(); //start asynchronously

        ForkJoinAdd secondTask = new ForkJoinAdd(numbers, start + length / 2, end);

        Long secondTaskResult = secondTask.compute();
        Long firstTaskResult = firstTask.join();

        return firstTaskResult + secondTaskResult;

    }

    private long add() {
        long result = 0;
        for (int i = start; i < end; i++) {
            result += numbers[i];
        }
        return result;
    }

    public static long startForkJoinSum(long n) {
        long[] numbers = LongStream.rangeClosed(1, n).toArray();
        ForkJoinTask task = new ForkJoinAdd(numbers);
        return new ForkJoinPool().invoke(task);
    }

}

Starte es. Summiere alle Zahlen von 1 bis 1 Million.

Main.java

package com.example.concurrency.forkjoin;

public class Main {

    public static void main(String[] args) {

        System.out.println(ForkJoinAdd.startForkJoinSum(1_000_000));

    }

}

Ausgabe

500000500000

2. Fork/Join – RecursiveAction

Ein Fork-Join-Beispiel zum Ermitteln der Fibonacci-Zahl mithilfe einer rekursiven Schleife.

Note
Diese Methode wird nur für die Fork / Join-Demo verwendet. Die rekursive Schleife ist langsam. Versuchen Sie dieseJava Fibonacci examples, um die Fibonacci-Zahl schneller zu finden.

ForkJoinFibonacci.java

package com.example.concurrency.forkjoin;

import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveAction;

public class ForkJoinFibonacci extends RecursiveAction {

    private static final long threshold = 10;
    private volatile long number;

    public ForkJoinFibonacci(long number) {
        this.number = number;
    }

    public long getNumber() {
        return number;
    }

    @Override
    protected void compute() {
        long n = number;
        if (n <= threshold) {
            number = fib(n);
        } else {
            ForkJoinFibonacci f1 = new ForkJoinFibonacci(n - 1);
            ForkJoinFibonacci f2 = new ForkJoinFibonacci(n - 2);
            ForkJoinTask.invokeAll(f1, f2);
            number = f1.number + f2.number;
        }
    }

    private static long fib(long n) {
        if (n <= 1) return n;
        else return fib(n - 1) + fib(n - 2);
    }

}

Führen Sie es aus, finden Sie die 50. Fibonacci-Zahl.

Main.java

package com.example.concurrency.forkjoin;

import java.util.concurrent.ForkJoinPool;

public class Main {

    public static void main(String[] args) {

        ForkJoinFibonacci task = new ForkJoinFibonacci(50);
        new ForkJoinPool().invoke(task);

        System.out.println(task.getNumber());

    }

}

Ausgabe

12586269025

Difference between RecursiveTask and RecursiveAction?
Beide sind gleich, nurRecursiveTask gibt einen Wert zurück, während RecursiveAction nichts zurückgibt, void.

Quellcode herunterladen