Статья посвящена такому интересному и полезному механизму (наборам механизмов и библиотек), как Платформа вилки/соединения .
Он позволяет многократно ускорить вычисления и добиться максимальных результатов обработки, используя все доступные возможности системы (процессоров).
В этой статье будут созданы классы, использующие Платформа вилки/соединения .
Код показывает один из возможных вариантов использования параллельного программирования.
Итак, начнем.
При создании приложений следует максимально разделить части, отвечающие за запуск, настройку и обработку данных.
И этот вариант работы с Fork/Join не является исключением.
В примерах будут использоваться классы Start, Stream, Calc соответственно.
Часть первая – запуск
Для тестирования создадим класс Start, он будет служить «точкой запуска».Значение timebetweenStartEnd покажет нам временной интервал между началом и окончанием вычислений.
Расчеты подразумевают возведение чисел от 0 до 1 000 000 в степени в двух вариантах в однопоточном и многопоточном режиме.
Класс Start определяет пул потоков ФоркДжоинПул() .
Использование метода вызвать() достигнут результат запуска задачи и ожидания ее завершения.
Значение компонентного значения определено как 1000000. Во вновь созданном экземпляре класса Stream определены исходные данные.
С помощью вызова() мы «переводим» эту задачу на выполнение.
import java.util.concurrent.ForkJoinPool; public class Start { public static void main(String[] args) { final int componentValue = 1000000; Long beginT = System.nanoTime(); ForkJoinPool fjp = new ForkJoinPool(); Stream test = new Stream(componentValue,0,componentValue); fjp.invoke(test); Long endT = System.nanoTime(); Long timebetweenStartEnd = endT - beginT; System.out.println("=====time========" +timebetweenStartEnd); } }
Часть вторая.
Настраивать.
Класс потока Вторая часть механизма представляет собой класс (Stream), отвечающий за настройку многопоточности.
Теперь у нас есть только два таких варианта: первый основан на количестве обрабатываемых значений в одном потоке (далее — «отсечка»), второй — на количестве процессоров (получается методом доступныепроцессоры() ).
Обратите внимание, что в этой статье не будет обсуждаться механизм динамического создания потоков в зависимости от количества процессоров и/или других условий.
Это тема следующей статьи.
Класс использует абстрактный метод вычислить() , отвечающий за запуск вычислений, в нашем случае это выбор опции расчета и запуск вычислений в методе go класса Calc. Использование метода вызватьВсе() Запустим подзадачи.
Из алгоритма понятно, что если у нас больше одного процессора, или значение отсечки (500000) больше/равно полученным частям, то расчет происходит. В примере мы разбиваем forSplit на несколько частей (две) и запускаем две подзадачи.
При изменении значения переменной countLimit или установке значения countProcessors равным единице будет запущена только одна задача обработки данных.
import java.util.concurrent.RecursiveAction;
public class Stream extends RecursiveAction {
final int countProcessors = Runtime.getRuntime().
availableProcessors(); final int countLimit = 500000; int start; int end; int forSplit; Stream(int componentValue,int startNumber, int endNumber) { forSplit = componentValue; start = startNumber; end = endNumber; } protected void compute() { if (countProcessors == 1 || end - start <= countLimit) { System.out.println("=run="); for(int i = start; i <= end; i++) { new Calc().
go(i);
}
} else {
int middle = (start + end)/ 2;
invokeAll(new Stream(forSplit, 0, middle),
new Stream(forSplit, middle+1, end));
}
}
}
Часть третья.
Выполнение расчета.
Класс вычислений Этот класс отвечает за возведение числа в степень.
Часть ниже предназначена для демонстрации и может содержать любые вычисления от перебора коллекций до записи данных в хранилище.
public class Calc {
public void go(int numberForCalc) {
for(int i = 0; i <= numberForCalc; i++) {
double pow = Math.pow(numberForCalc,100);
}
}
}
Вместо концовки
Этот материал будет полезен тем, кто только начал изучать параллельное программирование.Здесь показаны основы работы с небольшой частью функционала.
Обращаю внимание читателей, что при небольших расчетах время, затраченное на создание второй подзадачи, может оказаться больше времени, необходимого для завершения расчета.
В следующих статьях мы приблизимся к созданию гибкого функционала по запуску и определению максимально возможных параллельных потоков, а также затронем тему ограничений, связанных с одновременно выполняемыми командами.
Теги: #Параллельное программирование #многопоточность #многопоточное программирование #java8 #fork/join framework #Разработка веб-сайтов #java #OOP
-
Погода И Климат Земли
19 Oct, 24 -
8 Сентября Нас Выпустят...
19 Oct, 24 -
Linkmeup. Выпуск 3
19 Oct, 24 -
Цифровая Пятница 2017
19 Oct, 24