khaliullov_ramil_lab_1 is ready

This commit is contained in:
rakhaliullov
2025-03-22 10:08:16 +04:00
parent fbcc1bcf57
commit 1717107444
2 changed files with 214 additions and 0 deletions

View File

@@ -0,0 +1,95 @@
import java.util.Random;
import java.util.Scanner;
import java.util.concurrent.*;
public class MatrixNormalization {
private static int SIZE;
private static final int THREADS = Runtime.getRuntime().availableProcessors();
private static double[][] matrix;
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Enter the size of the matrix: ");
SIZE = scanner.nextInt();
matrix = new double[SIZE][SIZE];
generateMatrix();
System.out.println("Matrix generated.......");
long startTime = System.nanoTime();
normalizeSingleThread();
long endTime = System.nanoTime();
System.out.println("Single-threaded time: " + (endTime - startTime) / 1_000_000 + " ms");
generateMatrix();
ExecutorService executor = Executors.newFixedThreadPool(THREADS);
startTime = System.nanoTime();
normalizeThreadPool(executor);
endTime = System.nanoTime();
System.out.println("ThreadPoolExecutor time: " + (endTime - startTime) / 1_000_000 + " ms");
executor.shutdown();
generateMatrix();
ForkJoinPool forkJoinPool = new ForkJoinPool(THREADS);
startTime = System.nanoTime();
forkJoinPool.invoke(new ForkJoinNormalize(0, SIZE));
endTime = System.nanoTime();
System.out.println("ForkJoinPool time: " + (endTime - startTime) / 1_000_000 + " ms");
}
private static void generateMatrix() {
Random rand = new Random();
for (int i = 0; i < SIZE; i++)
for (int j = 0; j < SIZE; j++)
matrix[i][j] = rand.nextDouble() * 100;
}
private static double findMax() {
double max = Double.MIN_VALUE;
for (double[] row : matrix)
for (double val : row)
max = Math.max(max, val);
return max;
}
private static void normalizeSingleThread() {
double max = findMax();
for (int i = 0; i < SIZE; i++)
for (int j = 0; j < SIZE; j++)
matrix[i][j] /= max;
}
private static void normalizeThreadPool(ExecutorService executor) {
double max = findMax();
for (int i = 0; i < SIZE; i++) {
final int row = i;
executor.submit(() -> {
for (int j = 0; j < SIZE; j++)
matrix[row][j] /= max;
});
}
}
static class ForkJoinNormalize extends RecursiveAction {
private static final int THRESHOLD = 100;
private final int start, end;
ForkJoinNormalize(int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected void compute() {
double max = findMax();
if (end - start <= THRESHOLD) {
for (int i = start; i < end; i++)
for (int j = 0; j < SIZE; j++)
matrix[i][j] /= max;
} else {
int mid = (start + end) / 2;
invokeAll(new ForkJoinNormalize(start, mid), new ForkJoinNormalize(mid, end));
}
}
}
}

View File

@@ -0,0 +1,119 @@
# **Лабораторная работа №1**
## **Тема:** Разработка многопоточного приложения с использованием Java Concurrency
### **Цель работы:**
Разработка многопоточного приложения с использованием Java Concurrency согласно варианту задания.
Необходимо:
1. Разработать однопоточный вариант алгоритма и замерить время его работы.
2. Разработать параллельный вариант алгоритма с использованием ThreadPoolExecutor и замерить время его работы
3. Разработать параллельный вариант алгоритма с использованием ForkJoinPoll и замерить время его работы.
ВАЖНО: Массив генерируется до работы всех вариантов алгоритмов. Все три алгоритма обрабатывают три одинаковых массива.
---
### **Вариант:**
1 Разделить элементы матрицы на наибольший элемент.
---
### **Шаги для запуска:**
1. Перейти в директорию с исходными файлами.
2. Скомпилировать Java-код:
```sh
javac MatrixNormalization.java
```
3. Запустить программу:
```sh
java MatrixNormalization
```
---
## **Используемые технологии:**
- `java.util.concurrent` — инструменты для работы с многопоточностью (пулы потоков, синхронизация).
- `ForkJoinPool` — пул потоков для выполнения параллельных задач.
- `ExecutorService` управление пулом потоков.
- `RecursiveAction` — абстрактный класс из Fork/Join Framework, используемый для выполнения параллельных задач без возвращаемого результата.
---
## **Код:**
1. Однопоточный алгоритм:
```java
private static void normalizeSingleThread() {
double max = findMax();
for (int i = 0; i < SIZE; i++)
for (int j = 0; j < SIZE; j++)
matrix[i][j] /= max;
}
```
2. ThreadPoolExecutor
```java
private static void normalizeThreadPool(ExecutorService executor) {
double max = findMax();
for (int i = 0; i < SIZE; i++) {
final int row = i;
executor.submit(() -> {
for (int j = 0; j < SIZE; j++)
matrix[row][j] /= max;
});
}
}
```
3. ForkJoinPoll
```java
static class ForkJoinNormalize extends RecursiveAction {
private static final int THRESHOLD = 100;
private final int start, end;
ForkJoinNormalize(int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected void compute() {
double max = findMax();
if (end - start <= THRESHOLD) {
for (int i = start; i < end; i++)
for (int j = 0; j < SIZE; j++)
matrix[i][j] /= max;
} else {
int mid = (start + end) / 2;
invokeAll(new ForkJoinNormalize(start, mid), new ForkJoinNormalize(mid, end));
}
}
}
```
---
## **Описание работы программы:**
Программа создаёт квадратную матрицу **cols × rows** и выполняет нормализацию матрицы с использованием разных подходов к многопоточной обработке. Нормализация заключается в делении всех элементов матрицы на ее максимальный элемент.
---
## **Результаты работы:**
1. Работа алгоритмов на матрице 100 на 100:
```
Время выполнения однопоточного алгоритма: 23 мс
Время выполнения с потоками ThreadPoolExecutor: 22 мс
Время выполнения с потоками ForkJoinPool: 16 мс
```
2. Работа алгоритмов на матрице 500 на 500:
```
Время выполнения однопоточного алгоритма: 76 мс
Время выполнения с потоками ThreadPoolExecutor: 48 мс
Время выполнения с потоками ForkJoinPool: 37 мс
```
3. Работа алгоритмов на матрице 1000 на 1000:
```
Время выполнения однопоточного алгоритма: 118 мс
Время выполнения с потоками ThreadPoolExecutor: 82 мс
Время выполнения с потоками ForkJoinPool: 70 мс
```
---
## **Вывод:**
- При небольших матрицах многопоточные алгоритмы не дают значительных преимуществ из-за накладных расходов.
- При увеличении размера матрицы многопоточные подходы заметно ускоряют вычисления.
- ForkJoinPool эффективнее ThreadPoolExecutor за счет более гибкого механизма балансировки нагрузки.