Платформа fork/join доступна с Java 7, чтобы упростить написание параллельных программ. Мы можем реализовать фреймворк fork/join, расширив либо рекурсивную задачу
, либо Рекурсивное действие
1. Вилка/Соединение – Рекурсивная задача
Пример соединения вилки для суммирования всех чисел из диапазона.
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{ 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); } }
Запустите его. Суммируйте все числа от 1 до 1 миллиона.
package com.mkyong.concurrency.forkjoin; public class Main { public static void main(String[] args) { System.out.println(ForkJoinAdd.startForkJoinSum(1_000_000)); } }
Выход
500000500000
2. Вилка/Соединение – рекурсивное действие
Пример соединения вилки, чтобы найти число Фибоначчи с помощью рекурсивного цикла.
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-е число Фибоначчи.
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
Скачать Исходный Код
Рекомендации
- Oracle – Вилка/Присоединение
- Вилка Java – Присоединиться к бедствию
- Дуг Ли – Развилка Java/Платформа для объединения
- Википедия – Число Фибоначчи
- Примеры Фибоначчи Java
- Рекурсивная задача javadoc
- JAVADOC рекурсивного действия
Оригинал: “https://mkyong.com/java/java-fork-join-framework-examples/”