abakarov_arslan_lab_1
abakarov_arslan_lab_1
This commit is contained in:
BIN
abakarov_arslan_lab_1/Diagrama.png
Normal file
BIN
abakarov_arslan_lab_1/Diagrama.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
63
abakarov_arslan_lab_1/ForkJoinMatrixDivider.java
Normal file
63
abakarov_arslan_lab_1/ForkJoinMatrixDivider.java
Normal file
@@ -0,0 +1,63 @@
|
||||
import java.util.concurrent.RecursiveAction;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
|
||||
public class ForkJoinMatrixDivider {
|
||||
public static void divideMatrix(int[][] matrix) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
int max = findMax(matrix);
|
||||
ForkJoinPool pool = new ForkJoinPool();
|
||||
pool.invoke(new DivideTask(matrix, 0, matrix.length, max));
|
||||
pool.shutdown();
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
System.out.println("ForkJoinPool: " + (endTime - startTime) + "ms");
|
||||
}
|
||||
|
||||
private static class DivideTask extends RecursiveAction {
|
||||
private final int[][] matrix;
|
||||
private final int start;
|
||||
private final int end;
|
||||
private final int max;
|
||||
|
||||
DivideTask(int[][] matrix, int start, int end, int max) {
|
||||
this.matrix = matrix;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.max = max;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compute() {
|
||||
if (end - start <= 10) { // porog
|
||||
for (int i = start; i < end; i++) {
|
||||
for (int j = 0; j < matrix[i].length; j++) {
|
||||
matrix[i][j] /= max;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int mid = (start + end) / 2;
|
||||
DivideTask left = new DivideTask(matrix, start, mid, max);
|
||||
DivideTask right = new DivideTask(matrix, mid, end, max);
|
||||
invokeAll(left, right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static int findMax(int[][] matrix) {
|
||||
int max = matrix[0][0];
|
||||
for (int[] row : matrix) {
|
||||
for (int value : row) {
|
||||
if (value > max) {
|
||||
max = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int[][] matrix = MatrixGenerator.generateMatrix(1000, 1000);
|
||||
divideMatrix(matrix);
|
||||
}
|
||||
}
|
||||
|
||||
14
abakarov_arslan_lab_1/MatrixGenerator.java
Normal file
14
abakarov_arslan_lab_1/MatrixGenerator.java
Normal file
@@ -0,0 +1,14 @@
|
||||
import java.util.Random;
|
||||
|
||||
public class MatrixGenerator {
|
||||
public static int[][] generateMatrix(int rows, int cols) {
|
||||
int[][] matrix = new int[rows][cols];
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < rows; i++) {
|
||||
for (int j = 0; j < cols; j++) {
|
||||
matrix[i][j] = i+j;
|
||||
}
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
}
|
||||
28
abakarov_arslan_lab_1/SingleThreadedMatrixDivider.java
Normal file
28
abakarov_arslan_lab_1/SingleThreadedMatrixDivider.java
Normal file
@@ -0,0 +1,28 @@
|
||||
public class SingleThreadedMatrixDivider {
|
||||
public static void main(String[] args) {
|
||||
|
||||
int[][] matrix = MatrixGenerator.generateMatrix(1000, 1000);
|
||||
long startTime = System.currentTimeMillis();
|
||||
int max = findMax(matrix);
|
||||
for (int i = 0; i < matrix.length; i++) {
|
||||
for (int j = 0; j < matrix[i].length; j++) {
|
||||
matrix[i][j] /= max;
|
||||
}
|
||||
}
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
System.out.println("Single-flow: " + (endTime - startTime) + "ms");
|
||||
}
|
||||
|
||||
private static int findMax(int[][] matrix) {
|
||||
int max = matrix[0][0];
|
||||
for (int[] row : matrix) {
|
||||
for (int value : row) {
|
||||
if (value > max) {
|
||||
max = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
}
|
||||
48
abakarov_arslan_lab_1/ThreadPoolMatrixDivider.java
Normal file
48
abakarov_arslan_lab_1/ThreadPoolMatrixDivider.java
Normal file
@@ -0,0 +1,48 @@
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ThreadPoolMatrixDivider {
|
||||
public static void divideMatrix(int[][] matrix, int numThreads) {
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
int max = findMax(matrix);
|
||||
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
|
||||
|
||||
for (int i = 0; i < matrix.length; i++) {
|
||||
final int row = i;
|
||||
executor.submit(() -> {
|
||||
for (int j = 0; j < matrix[row].length; j++) {
|
||||
matrix[row][j] /= max;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
executor.shutdown();
|
||||
try {
|
||||
executor.awaitTermination(1, TimeUnit.MINUTES);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
System.out.println("ThreadPoolExecutor: " + (endTime - startTime) + "ms");
|
||||
}
|
||||
|
||||
private static int findMax(int[][] matrix) {
|
||||
int max = matrix[0][0];
|
||||
for (int[] row : matrix) {
|
||||
for (int value : row) {
|
||||
if (value > max) {
|
||||
max = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
int[][] matrix = MatrixGenerator.generateMatrix(1000, 1000);
|
||||
divideMatrix(matrix, 4);
|
||||
}
|
||||
}
|
||||
91
abakarov_arslan_lab_1/readme.md
Normal file
91
abakarov_arslan_lab_1/readme.md
Normal file
@@ -0,0 +1,91 @@
|
||||
Лабораторная работа №1
|
||||
Разработка многопоточного приложения с использованием Java Concurrency согласно варианту задания.
|
||||
|
||||
Необходимо:
|
||||
Разработать однопоточный вариант алгоритма и замерить время его работы.
|
||||
Разработать параллельный вариант алгоритма с использованием ThreadPoolExecutor и замерить время его работы.
|
||||
Разработать параллельный вариант алгоритма с использованием ForkJoinPoll и замерить время его работы.
|
||||
!!!. Массив генерируется до работы всех вариантов алгоритмов. Все три алгоритма обрабатывают три одинаковых массива.
|
||||
|
||||
Вариант задания 1: Разделить элементы матрицы на наибольший элемент.
|
||||
|
||||
Как запустить лабораторную работу:
|
||||
javac ForkJoinMatrixDivider.java компилирует исходный код java ForkJoinMatrixDivider команда запускает скомпилированный класс
|
||||
javac SingleThreadedMatrixDivider.java компилирует исходный код java SingleThreadedMatrixDivider команда запускает скомпилированный класс
|
||||
javac ThreadPoolMatrixDivider.java компилирует исходный код java ThreadPoolMatrixDivider команда запускает скомпилированный класс
|
||||
|
||||
|
||||
Какие технологии использовали:
|
||||
Java 17+
|
||||
|
||||
ExecutorService (ThreadPoolExecutor)
|
||||
|
||||
ForkJoinPool
|
||||
|
||||
System.currentTimeMillis() для замеров времени выполнения
|
||||
|
||||
Как работает программа:
|
||||
Генерация матрицы:
|
||||
|
||||
Программа создаёт двумерный массив заданного размера.
|
||||
|
||||
Заполняет его случайными значениями.
|
||||
|
||||
Определяет наибольший элемент матрицы.
|
||||
|
||||
Однопоточный алгоритм:
|
||||
|
||||
Проходит по всей матрице в одном потоке.
|
||||
|
||||
Делит каждый элемент матрицы на наибольший элемент.
|
||||
|
||||
Записывает результат в новую матрицу.
|
||||
|
||||
Измеряет время выполнения.
|
||||
|
||||
Параллельный алгоритм с ThreadPoolExecutor:
|
||||
|
||||
Создаёт пул потоков с фиксированным количеством потоков (обычно равное количеству ядер CPU).
|
||||
|
||||
Делит матрицу на строки, назначая обработку каждой строки отдельному потоку.
|
||||
|
||||
Потоки выполняют деление элементов и записывают результаты.
|
||||
|
||||
Ожидает завершения всех потоков.
|
||||
|
||||
Измеряет время выполнения.
|
||||
|
||||
Параллельный алгоритм с ForkJoinPool:
|
||||
|
||||
Использует принцип рекурсивного разбиения задач (Fork/Join).
|
||||
|
||||
Разбивает матрицу на более мелкие подзадачи, пока они не станут достаточно малы для обработки в одном потоке.
|
||||
|
||||
Выполняет деление элементов параллельно.
|
||||
|
||||
Объединяет результаты.
|
||||
|
||||
Измеряет время выполнения.
|
||||
|
||||
Вывод результатов:
|
||||
|
||||
Для каждого метода измеряется время выполнения.
|
||||
|
||||
Результаты выводятся в консоль.
|
||||
|
||||
(Размер матрицы 1000х1000)
|
||||
Single thread alghoritm: 51 ms
|
||||
ThreadPoolExecutor: 150 ms
|
||||
ForkJoinPool: 90 ms
|
||||
(Размер матрицы 2000х2000)
|
||||
Single thread alghoritm: 242 ms
|
||||
ThreadPoolExecutor: 300 ms
|
||||
ForkJoinPool: 139 ms.
|
||||
(Размер матрицы 3000x3000)
|
||||
Single thread alghoritm: 452 ms
|
||||
ThreadPoolExecutor: 495 ms
|
||||
ForkJoinPool: 411 ms
|
||||
|
||||
|
||||
Вывод
|
||||
Использование ForkJoinPool демонстрирует наивысшую эффективность среди многопоточных подходов в этом алгоритме. ThreadPoolExecutor оказывается самым невыгодным из-за значительных накладных расходов, связанных с управлением потоками. Однопоточный метод работает достаточно хорошо на небольших объемах данных, однако с ростом вычислительной нагрузки он существенно уступает ForkJoinPool.
|
||||
Reference in New Issue
Block a user