abakarov_arslan_lab_1

abakarov_arslan_lab_1
This commit is contained in:
2025-03-21 23:16:33 +04:00
parent c3d5ac3ba2
commit 28f40483ad
6 changed files with 244 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View 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);
}
}

View 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;
}
}

View 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;
}
}

View 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);
}
}

View 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.