forked from sevastyan_b/SSPR_25
buslaev_roman_lab_1 is ready
This commit is contained in:
113
buslaev_roman_lab_1/Main.java
Normal file
113
buslaev_roman_lab_1/Main.java
Normal file
@@ -0,0 +1,113 @@
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.*;
|
||||
|
||||
import static java.lang.Math.min;
|
||||
|
||||
public class Main {
|
||||
private static final int ROWS = 10000;
|
||||
private static final int COLS = 10000;
|
||||
private static final int THREADS = 4;
|
||||
|
||||
public static final long MaxValue = 1000000;
|
||||
|
||||
public static void main(String[] args) {
|
||||
long[][] matrix = generateMatrix(ROWS, COLS);
|
||||
|
||||
long start = System.nanoTime();
|
||||
long minSingle = findMinSingleThread(matrix);
|
||||
long end = System.nanoTime();
|
||||
System.out.println("Single: Min number - " + minSingle + ", Time: " + (end - start) / 1000000 + " мс");
|
||||
|
||||
start = System.nanoTime();
|
||||
long minThreadPool = findMinThreadPool(matrix);
|
||||
end = System.nanoTime();
|
||||
System.out.println("ThreadPoolExecutor: Min number - " + minThreadPool + ", Time: " + (end - start) / 1000000 + " мс");
|
||||
|
||||
start = System.nanoTime();
|
||||
long minForkJoin = findMinForkJoin(matrix);
|
||||
end = System.nanoTime();
|
||||
System.out.println("ForkJoinPool: Min number - " + minForkJoin + ", Time: " + (end - start) / 1000000 + " мс");
|
||||
}
|
||||
|
||||
private static long[][] generateMatrix(int rows, int cols) {
|
||||
Random rand = new Random();
|
||||
long[][] matrix = new long[rows][cols];
|
||||
for (int i = 0; i < rows; i++) {
|
||||
for (int j = 0; j < cols; j++) {
|
||||
matrix[i][j] = rand.nextLong(MaxValue);
|
||||
}
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
|
||||
private static long findMinSingleThread(long[][] matrix) {
|
||||
long my_min = matrix[0][0];
|
||||
for(int i = 0; i < matrix.length; i++){
|
||||
my_min = min(my_min, findMinInRaw(matrix[i]));
|
||||
}
|
||||
return my_min;
|
||||
}
|
||||
|
||||
private static long findMinInRaw(long[] arr){
|
||||
long my_min = arr[0];
|
||||
for(int i = 1; i < arr.length; i++){
|
||||
my_min = min(my_min, arr[i]);
|
||||
}
|
||||
return my_min;
|
||||
}
|
||||
|
||||
private static long findMinThreadPool(long[][] matrix) {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(THREADS);
|
||||
List<Future<Long>> results = new ArrayList<>();
|
||||
|
||||
for (long[] row : matrix) {
|
||||
results.add(executor.submit(() -> findMinInRaw(row)));
|
||||
}
|
||||
|
||||
long min = MaxValue;
|
||||
for (Future<Long> future : results) {
|
||||
try {
|
||||
min = min(min, future.get());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
executor.shutdown();
|
||||
return min;
|
||||
}
|
||||
|
||||
private static long findMinForkJoin(long[][] matrix) {
|
||||
ForkJoinPool pool = new ForkJoinPool();
|
||||
return pool.invoke(new MinTask(matrix, 0, matrix.length));
|
||||
}
|
||||
|
||||
static class MinTask extends RecursiveTask<Long> {
|
||||
private static final int MAX_ROWS = 1000;
|
||||
private final long[][] matrix;
|
||||
private final int startRow, endRow;
|
||||
|
||||
MinTask(long[][] matrix, int startRow, int endRow) {
|
||||
this.matrix = matrix;
|
||||
this.startRow = startRow;
|
||||
this.endRow = endRow;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Long compute() {
|
||||
if (endRow - startRow <= MAX_ROWS) {
|
||||
long my_min = Long.MAX_VALUE;
|
||||
for (int i = startRow; i < endRow; i++) {
|
||||
my_min = min(my_min, findMinInRaw(matrix[i]));
|
||||
}
|
||||
return my_min;
|
||||
}
|
||||
int mid = (startRow + endRow) / 2;
|
||||
MinTask leftTask = new MinTask(matrix, startRow, mid);
|
||||
MinTask rightTask = new MinTask(matrix, mid, endRow);
|
||||
invokeAll(leftTask, rightTask);
|
||||
return min(leftTask.join(), rightTask.join());
|
||||
}
|
||||
}
|
||||
}
|
||||
77
buslaev_roman_lab_1/README.md
Normal file
77
buslaev_roman_lab_1/README.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# Лабораторная работа №1
|
||||
|
||||
Разработка многопоточного приложения с использованием Java Concurrency.
|
||||
Мой вариант -> 4) Определить минимальный элемент матрицы.
|
||||
|
||||
## Цель
|
||||
|
||||
Сравнить время выполнения трех реализаций алгоритма поиска минимального элемента в большой матрице:
|
||||
1. Однопоточный алгоритм.
|
||||
2. Многопоточный алгоритм с использованием `ThreadPoolExecutor`.
|
||||
3. Многопоточный алгоритм с использованием `ForkJoinPool`.
|
||||
|
||||
Все три алгоритма обрабатывают один и тот же массив, который генерируется один раз перед запуском.
|
||||
|
||||
---
|
||||
|
||||
## Описание программы
|
||||
|
||||
1. **Генерация матрицы**
|
||||
Метод `generateMatrix(...)` создает матрицу размером `ROWS x COLS`, заполняя ее случайными числами, используя `Random.nextLong(MaxValue)`.
|
||||
|
||||
2. **Однопоточный поиск минимума**
|
||||
- `findMinSingleThread(...)` обходит все строки и для каждой строки вызывает `findMinInRaw(...)` (локальный поиск минимума в одномерном массиве).
|
||||
- Возвращается общий минимальный элемент по всей матрице.
|
||||
|
||||
3. **Поиск минимума с `ThreadPoolExecutor`**
|
||||
- `findMinThreadPool(...)` создает пул потоков из `THREADS`.
|
||||
- Для каждой строки матрицы отправляет задачу (`Callable<Long>`), которая в свою очередь вызывает `findMinInRaw(...)` для поиска минимума в одной строке.
|
||||
- Собираются результаты всех `Future<Long>`, ищется минимальный элемент из их значений.
|
||||
|
||||
4. **Поиск минимума с `ForkJoinPool`**
|
||||
- `findMinForkJoin(...)` создает `ForkJoinPool` и запускает рекурсивную задачу `MinTask`.
|
||||
- `MinTask` (наследует `RecursiveTask<Long>`) делит промежуток строк на две части, пока не достигнет порога `MAX_ROWS`. Когда участок достаточно мал, последовательно ищет минимум по строкам.
|
||||
- Объединяет (берет минимум) из двух подзадач.
|
||||
|
||||
5. **Замер времени**
|
||||
- В `main(...)` для каждого из трех алгоритмов замеряется время до и после выполнения (через `System.nanoTime()`).
|
||||
- Результаты выводятся в консоль.
|
||||
|
||||
---
|
||||
|
||||
## Как запустить
|
||||
|
||||
1. Установить JDK (Java 8 или выше).
|
||||
2. Скомпилировать:
|
||||
```bash
|
||||
javac Main.java
|
||||
```
|
||||
3. Запустить:
|
||||
```bash
|
||||
java Main
|
||||
```
|
||||
4. По завершении вы увидите три строки с минимальным элементом и временем выполнения (в мс) для:
|
||||
- Однопоточного алгоритма
|
||||
- Алгоритма с `ThreadPoolExecutor`
|
||||
- Алгоритма с `ForkJoinPool`
|
||||
|
||||
---
|
||||
|
||||
## Пример вывода
|
||||
|
||||
```
|
||||
Single: Min number - 0, Time: 107 мс
|
||||
ThreadPoolExecutor: Min number - 0, Time: 102 мс
|
||||
ForkJoinPool: Min number - 0, Time: 63 мс
|
||||
```
|
||||
|
||||
Числа зависят от размера матрицы и мощности процессора.
|
||||
Чтобы было более наглядно видно разницу по времени между всеми реализации алгоритма, нужно более большую матрицу.
|
||||
|
||||
---
|
||||
|
||||
## Вывод
|
||||
1. **Однопоточный** вариант прост в реализации, но при больших размерах матрицы работает долго.
|
||||
2. **ThreadPoolExecutor** позволяет распараллелить обработку строк матрицы и значительно ускорить поиск.
|
||||
3. **ForkJoinPool** часто дает еще более высокое ускорение за счет механизма рекурсивного разбиения задач, но реальная производительность зависит от конфигурации процессоров и параметров разбиения.
|
||||
|
||||
Reference in New Issue
Block a user