Фреймворк fork-join позволяет разбить определенную задачу на нескольких рабочих, а затем дождаться результата, чтобы объединить их. Он в значительной степени использует возможности многопроцессорной машины. Ниже приведены основные понятия и объекты, используемые в инфраструктуре fork-join.
вилка
Форк — это процесс, в котором задача разделяется на более мелкие и независимые подзадачи, которые могут выполняться одновременно.
Синтаксис
Sum left = new Sum(array, low, mid); left.fork();
Здесь Sum является подклассом RecursiveTask, а left.fork () разбивает задачу на подзадачи.
Присоединиться
Присоединение — это процесс, в котором задача объединяет все результаты подзадач после завершения выполнения подзадач, в противном случае она продолжает ждать.
Синтаксис
left.join();
Здесь слева находится объект класса Sum.
ForkJoinPool
это специальный пул потоков, предназначенный для работы с разделением задач по типу ветвления и объединения.
Синтаксис
ForkJoinPool forkJoinPool = new ForkJoinPool(4);
Здесь новый ForkJoinPool с уровнем параллелизма 4 процессоров.
RecursiveAction
RecursiveAction представляет задачу, которая не возвращает никакого значения.
Синтаксис
class Writer extends RecursiveAction { @Override protected void compute() { } }
RecursiveTask
RecursiveTask представляет задачу, которая возвращает значение.
Синтаксис
class Sum extends RecursiveTask<Long> { @Override protected Long compute() { return null; } }
пример
Следующая программа TestThread показывает использование инфраструктуры Fork-Join в среде, основанной на потоках.
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; } } } }
Это даст следующий результат.