fork/joinフレームワークは、Java 7以降で使用でき、並列プログラムの作成を容易にします。

RecursiveTask`または

RecursiveAction`のいずれかを拡張することによって、fork/joinフレームワークを実装できます

1.フォーク/結合 – RecursiveTask

範囲からすべての数値を合計するフォーク結合の例。

ForkJoinAdd.java

package com.mkyong.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<Long> {

    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<Long> task = new ForkJoinAdd(numbers);
        return new ForkJoinPool().invoke(task);
    }

}

それを実行します。 1から100万までのすべての数値を合計します。

Main.java

package com.mkyong.concurrency.forkjoin;

public class Main {

    public static void main(String[]args) {

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

    }

}

出力

500000500000

2.フォーク/結合 – RecursiveAction

再帰的ループを使用してフィボナッチ数を見つけるフォーク結合の例。

  • 注意** このメソッドは、Fork/Joinデモ専用です。再帰ループは遅いです。フィボナッチ数をより速く見つけるには、//java/java-fibonacci-examples/[Java Fibonacciの例]を参照してください。

ForkJoinFibonacci.java

package com.mkyong.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);
    }

}

それを実行して、フィボナッチ数50番目を見つけてください。

Main.java

package com.mkyong.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());

    }

}

出力

12586269025

  • RecursiveTaskとRecursiveActionの違い?** +どちらも同じですが、 `RecursiveTask`は値を返し、RecursiveActionは何も返しません。

ソースコードをダウンロードする

参考文献

フレームワーク]。

https://en.wikipedia.org/wiki/Fibonacci__number

[ウィキペディア – フィボナッチ

数]。リンク://java/java-fibonacci-examples/[Javaフィボナッチの例]

JavaDoc]