forked from sevastyan_b/SSPR_25
petrov_ilya_lab_1 is ready
This commit is contained in:
parent
4661f77f23
commit
0333cdc287
182
petrov_ilya_lab_1/README.md
Normal file
182
petrov_ilya_lab_1/README.md
Normal file
@ -0,0 +1,182 @@
|
||||
# Лабораторная работа №1.
|
||||
|
||||
**Разработка многопоточного приложения с использованием Java Concurrency согласно варианту задания.**
|
||||
|
||||
Необходимо выполнить следующие задачи:
|
||||
|
||||
1. Разработать однопоточный вариант алгоритма и замерить время его работы.
|
||||
2. Разработать параллельный вариант алгоритма с использованием ThreadPoolExecutor и замерить время его работы
|
||||
3. Разработать параллельный вариант алгоритма с использованием ForkJoinPoll и замерить время его работы.
|
||||
|
||||
## Вариант задания
|
||||
|
||||
21. Упорядочить столбцы матрицы по возрастанию первых элементов.
|
||||
|
||||
## Как запустить программу
|
||||
|
||||
1. Для начала, необходимо локально создать аналогичную (или собственную) иерархию файлов программы:
|
||||
|
||||
Например:
|
||||
|
||||
- project_java (название директории/проекта)
|
||||
|
||||
- /src (папка с файлами программы, но необязательна)
|
||||
|
||||
- ForkJoinSorter.java
|
||||
- Main.java
|
||||
- MatrixUtils.java
|
||||
- SingleThreadSorter.java
|
||||
- ThreadPoolSorter.java
|
||||
|
||||
2. Далее, необходимо скопировать код из каждого файла, расположенного в удалённой ветке на гите, в локальные файлы, находящиеся внутри директории _src_.
|
||||
|
||||
3. Внутри директории, где расположены файлы программы (например, _src_), с помощью командной строки скомпилировать программу следующей командой:
|
||||
|
||||
> javac Main.java
|
||||
|
||||
4. Убедившись, что компиляция прошла успешно (никаких ошибок в процессе компиляции не возникло), запустить программу следующей командой:
|
||||
|
||||
> java Main.java <кол-во строк матрицы (целое число)> <кол-во столбцов матрицы (целое число)>
|
||||
|
||||
**Внимание:**
|
||||
|
||||
Можно скомпилировать программу, указав в качестве доп. параметра выходную директории (то есть папку, куда, в конечном итоге, будет скомпилирована программа). И далее, перейти в эту папку, и оттуда запустить программу:
|
||||
|
||||
> javac -d /путь/к/выходной/директории Main.java
|
||||
|
||||
> java Main.java <кол-во строк матрицы (целое число)> <кол-во столбцов матрицы (целое число)>
|
||||
|
||||
## Инструменты
|
||||
|
||||
- **Язык программирования**: Java
|
||||
- **Пакеты**:
|
||||
- `java.util.concurrent` — используется для реализации многопоточности через `ThreadPoolExecutor` и `ForkJoinPool`
|
||||
- **Среда разработки**: IntelliJ IDEA
|
||||
- **Версия JDK**: 21
|
||||
- **Алгоритмы сортировки**:
|
||||
- **Однопоточная сортировка** — реализована вручную с использованием сортировки столбцов
|
||||
- **ThreadPoolExecutor** — для многопоточной обработки столбцов с использованием пула потоков
|
||||
- **ForkJoinPool** — для многопоточной обработки столбцов с использованием рекурсивных задач
|
||||
|
||||
## Как работает программа
|
||||
|
||||
Программа выполняет сортировку столбцов матрицы по убыванию первых элементов с использованием различных подходов многозадачности:
|
||||
|
||||
1. **Однопоточная версия**: сортирует столбцы матрицы с использованием стандартной сортировки.
|
||||
2. **Параллельная версия с использованием ThreadPoolExecutor**: выполняет сортировку столбцов с использованием пула потоков для ускорения работы.
|
||||
3. **Параллельная версия с использованием ForkJoinPool**: использует рекурсивное разделение задач для оптимизации работы с большими массивами данных.
|
||||
|
||||
Программа генерирует случайную матрицу (с заданным размером), затем выполняет сортировку для каждого из вариантов и замеряет время выполнения каждого из алгоритмов. Результаты выводятся на экран и записываются в файл.
|
||||
|
||||
## Тесты
|
||||
|
||||
#### Пример №1
|
||||
|
||||
##### Входные данные
|
||||
|
||||
```
|
||||
| 60 | 873 | 81 | 801 | 45 | 838 | 231 |
|
||||
| 583 | 576 | 207 | 148 | 919 | 809 | 130 |
|
||||
| 574 | 390 | 21 | 4 | 960 | 350 | 930 |
|
||||
| 103 | 917 | 619 | 731 | 242 | 16 | 587 |
|
||||
| 528 | 789 | 815 | 800 | 330 | 416 | 141 |
|
||||
| 19 | 211 | 831 | 598 | 382 | 572 | 212 |
|
||||
| 365 | 973 | 680 | 41 | 474 | 922 | 750 |
|
||||
```
|
||||
|
||||
##### Выходные данные
|
||||
|
||||
```
|
||||
| 873 | 838 | 801 | 231 | 81 | 60 | 45 |
|
||||
| 576 | 809 | 148 | 130 | 207 | 583 | 919 |
|
||||
| 390 | 350 | 4 | 930 | 21 | 574 | 960 |
|
||||
| 917 | 16 | 731 | 587 | 619 | 103 | 242 |
|
||||
| 789 | 416 | 800 | 141 | 815 | 528 | 330 |
|
||||
| 211 | 572 | 598 | 212 | 831 | 19 | 382 |
|
||||
| 973 | 922 | 41 | 750 | 680 | 365 | 474 |
|
||||
```
|
||||
|
||||
#### Пример №2
|
||||
|
||||
##### Входные данные
|
||||
|
||||
```
|
||||
| 549 | 708 | 958 | 340 | 836 | 575 | 748 |
|
||||
| 235 | 699 | 906 | 895 | 731 | 957 | 936 |
|
||||
| 776 | 690 | 156 | 377 | 985 | 995 | 995 |
|
||||
| 906 | 713 | 410 | 559 | 760 | 694 | 158 |
|
||||
| 16 | 474 | 825 | 784 | 141 | 59 | 443 |
|
||||
| 447 | 909 | 521 | 406 | 845 | 66 | 229 |
|
||||
| 582 | 473 | 856 | 439 | 166 | 721 | 676 |
|
||||
```
|
||||
|
||||
##### Выходные данные
|
||||
|
||||
```
|
||||
| 958 | 836 | 748 | 708 | 575 | 549 | 340 |
|
||||
| 906 | 731 | 936 | 699 | 957 | 235 | 895 |
|
||||
| 156 | 985 | 995 | 690 | 995 | 776 | 377 |
|
||||
| 410 | 760 | 158 | 713 | 694 | 906 | 559 |
|
||||
| 825 | 141 | 443 | 474 | 59 | 16 | 784 |
|
||||
| 521 | 845 | 229 | 909 | 66 | 447 | 406 |
|
||||
| 856 | 166 | 676 | 473 | 721 | 582 | 439 |
|
||||
```
|
||||
|
||||
#### Пример №3
|
||||
|
||||
##### Входные данные
|
||||
|
||||
```
|
||||
| 901 | 186 | 700 | 766 | 397 | 422 | 762 |
|
||||
| 575 | 966 | 882 | 884 | 220 | 440 | 201 |
|
||||
| 850 | 660 | 909 | 964 | 257 | 177 | 800 |
|
||||
| 977 | 495 | 832 | 426 | 592 | 769 | 170 |
|
||||
| 994 | 769 | 347 | 784 | 56 | 225 | 643 |
|
||||
| 739 | 327 | 700 | 714 | 721 | 157 | 404 |
|
||||
| 240 | 612 | 992 | 855 | 811 | 756 | 230 |
|
||||
```
|
||||
|
||||
##### Выходные данные
|
||||
|
||||
```
|
||||
| 901 | 766 | 762 | 700 | 422 | 397 | 186 |
|
||||
| 575 | 884 | 201 | 882 | 440 | 220 | 966 |
|
||||
| 850 | 964 | 800 | 909 | 177 | 257 | 660 |
|
||||
| 977 | 426 | 170 | 832 | 769 | 592 | 495 |
|
||||
| 994 | 784 | 643 | 347 | 225 | 56 | 769 |
|
||||
| 739 | 714 | 404 | 700 | 157 | 721 | 327 |
|
||||
| 240 | 855 | 230 | 992 | 756 | 811 | 612 |
|
||||
```
|
||||
|
||||
## Результаты работы на матрице 10000 \* 10000
|
||||
|
||||
#### Тест №1
|
||||
|
||||
```
|
||||
|
||||
Время сортировки (однопоточный режим): 1615 мс
|
||||
Время сортировки (ThreadPoolExecutor): 740 мс
|
||||
Время сортировки (ForkJoinPool): 1040 мс
|
||||
```
|
||||
|
||||
#### Тест №2
|
||||
|
||||
```
|
||||
Время сортировки (однопоточный режим): 1789 мс
|
||||
Время сортировки (ThreadPoolExecutor): 743 мс
|
||||
Время сортировки (ForkJoinPool): 1020 мс
|
||||
```
|
||||
|
||||
#### Тест №3
|
||||
|
||||
```
|
||||
Время сортировки (однопоточный режим): 1613 мс
|
||||
Время сортировки (ThreadPoolExecutor): 696 мс
|
||||
Время сортировки (ForkJoinPool): 1068 мс
|
||||
```
|
||||
|
||||
## Вывод
|
||||
|
||||
ThreadExecutor показал наименьшее время выполнения, потому что он эффективно распределяет задачи между несколькими потоками, уменьшая время ожидания на обработку каждого столбца матрицы.
|
||||
|
||||
В целом использование потоков ускоряет выполнение, так как позволяет параллельно обрабатывать несколько частей данных, в отличие от последовательной обработки без потоков.
|
20
petrov_ilya_lab_1/src/ForkJoinSorter.java
Normal file
20
petrov_ilya_lab_1/src/ForkJoinSorter.java
Normal file
@ -0,0 +1,20 @@
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
|
||||
public class ForkJoinSorter {
|
||||
public static void sort(int[][] matrix) {
|
||||
ForkJoinPool pool = new ForkJoinPool();
|
||||
Integer[] indices = new Integer[matrix[0].length];
|
||||
for (int i = 0; i < indices.length; i++)
|
||||
indices[i] = i;
|
||||
|
||||
Arrays.sort(indices, (a, b) -> Integer.compare(matrix[0][b], matrix[0][a]));
|
||||
|
||||
int[][] sorted = new int[matrix.length][matrix[0].length];
|
||||
pool.invoke(new ForkJoinTask(matrix, sorted, indices, 0, indices.length));
|
||||
pool.shutdown();
|
||||
|
||||
for (int i = 0; i < matrix.length; i++)
|
||||
System.arraycopy(sorted[i], 0, matrix[i], 0, indices.length);
|
||||
}
|
||||
}
|
32
petrov_ilya_lab_1/src/ForkJoinTask.java
Normal file
32
petrov_ilya_lab_1/src/ForkJoinTask.java
Normal file
@ -0,0 +1,32 @@
|
||||
import java.util.concurrent.RecursiveAction;
|
||||
|
||||
public class ForkJoinTask extends RecursiveAction {
|
||||
int[][] matrix;
|
||||
int[][] sorted;
|
||||
Integer[] indices;
|
||||
int start, end;
|
||||
static final int THRESHOLD = 5;
|
||||
|
||||
ForkJoinTask(int[][] matrix, int[][] sorted, Integer[] indices, int start, int end) {
|
||||
this.matrix = matrix;
|
||||
this.sorted = sorted;
|
||||
this.indices = indices;
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void compute() {
|
||||
if (end - start <= THRESHOLD) {
|
||||
for (int i = start; i < end; i++) {
|
||||
for (int row = 0; row < matrix.length; row++) {
|
||||
sorted[row][i] = matrix[row][indices[i]];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int mid = (start + end) / 2;
|
||||
invokeAll(new ForkJoinTask(matrix, sorted, indices, start, mid), new ForkJoinTask(matrix, sorted, indices
|
||||
, mid, end));
|
||||
}
|
||||
}
|
||||
}
|
62
petrov_ilya_lab_1/src/Main.java
Normal file
62
petrov_ilya_lab_1/src/Main.java
Normal file
@ -0,0 +1,62 @@
|
||||
import java.io.*;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length != 2) {
|
||||
System.out.println("Usage: java MatrixSorter <rows> <columns>");
|
||||
return;
|
||||
}
|
||||
|
||||
int rows = Integer.parseInt(args[0]);
|
||||
int cols = Integer.parseInt(args[1]);
|
||||
|
||||
int[][] matrix = MatrixUtils.generateMatrix(rows, cols);
|
||||
int[][] matrixCopy1 = MatrixUtils.copyMatrix(matrix);
|
||||
int[][] matrixCopy2 = MatrixUtils.copyMatrix(matrix);
|
||||
|
||||
BufferedWriter writer = new BufferedWriter(new FileWriter("matrix_output.txt"));
|
||||
|
||||
writer.write("Original Matrix:\n");
|
||||
MatrixUtils.printMatrixToFile(matrix, writer);
|
||||
|
||||
System.out.println("Initial Matrix (first 10 elements):");
|
||||
MatrixUtils.printMatrix(matrix);
|
||||
|
||||
long startTime, endTime;
|
||||
|
||||
// Single-threaded
|
||||
startTime = System.currentTimeMillis();
|
||||
SingleThreadSorter.sortColumns(matrix);
|
||||
endTime = System.currentTimeMillis();
|
||||
System.out.println("\nSingle-threaded (first 10 elements):");
|
||||
MatrixUtils.printMatrix(matrix);
|
||||
writer.write("\nSingle-threaded:\n");
|
||||
MatrixUtils.printMatrixToFile(matrix, writer);
|
||||
writer.write("Single-threaded time: " + (endTime - startTime) + "ms\n");
|
||||
System.out.println("Single-threaded time: " + (endTime - startTime) + "ms\n");
|
||||
|
||||
// ThreadPoolExecutor
|
||||
startTime = System.currentTimeMillis();
|
||||
ThreadPoolSorter.sort(matrixCopy1);
|
||||
endTime = System.currentTimeMillis();
|
||||
System.out.println("\nThreadPoolExecutor (first 10 elements):");
|
||||
MatrixUtils.printMatrix(matrixCopy1);
|
||||
writer.write("\nThreadPoolExecutor:\n");
|
||||
MatrixUtils.printMatrixToFile(matrixCopy1, writer);
|
||||
writer.write("ThreadPoolExecutor time: " + (endTime - startTime) + "ms\n");
|
||||
System.out.println("ThreadPoolExecutor time: " + (endTime - startTime) + "ms\n");
|
||||
|
||||
// ForkJoinPool
|
||||
startTime = System.currentTimeMillis();
|
||||
ForkJoinSorter.sort(matrixCopy2);
|
||||
endTime = System.currentTimeMillis();
|
||||
System.out.println("\nForkJoinPool (first 10 elements):");
|
||||
MatrixUtils.printMatrix(matrixCopy2);
|
||||
writer.write("\nSorted Matrix (ForkJoinPool):\n");
|
||||
MatrixUtils.printMatrixToFile(matrixCopy2, writer);
|
||||
writer.write("ForkJoinPool time: " + (endTime - startTime) + "ms");
|
||||
System.out.println("ForkJoinPool time: " + (endTime - startTime) + "ms");
|
||||
|
||||
writer.close();
|
||||
}
|
||||
}
|
42
petrov_ilya_lab_1/src/MatrixUtils.java
Normal file
42
petrov_ilya_lab_1/src/MatrixUtils.java
Normal file
@ -0,0 +1,42 @@
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
public class MatrixUtils {
|
||||
public static int[][] generateMatrix(int rows, int cols) {
|
||||
Random rand = new Random();
|
||||
int[][] matrix = new int[rows][cols];
|
||||
for (int i = 0; i < rows; i++)
|
||||
for (int j = 0; j < cols; j++)
|
||||
matrix[i][j] = rand.nextInt(1000);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
public static int[][] copyMatrix(int[][] matrix) {
|
||||
return Arrays.stream(matrix).map(int[]::clone).toArray(int[][]::new);
|
||||
}
|
||||
|
||||
public static void printMatrix(int[][] matrix) {
|
||||
for (int i = 0; i < Math.min(matrix.length, 10); i++) {
|
||||
for (int j = 0; j < Math.min(matrix[i].length, 10); j++) {
|
||||
System.out.printf("%5d", matrix[i][j]);
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
}
|
||||
|
||||
public static void printMatrixToFile(int[][] matrix, BufferedWriter writer) throws IOException {
|
||||
int count = 0;
|
||||
for (int[] row : matrix) {
|
||||
for (int val : row) {
|
||||
if (count < 100) {
|
||||
writer.write(String.format("%5d", val));
|
||||
count++;
|
||||
} else
|
||||
return;
|
||||
}
|
||||
writer.newLine();
|
||||
}
|
||||
}
|
||||
}
|
22
petrov_ilya_lab_1/src/SingleThreadSorter.java
Normal file
22
petrov_ilya_lab_1/src/SingleThreadSorter.java
Normal file
@ -0,0 +1,22 @@
|
||||
import java.util.Arrays;
|
||||
|
||||
public class SingleThreadSorter {
|
||||
public static void sortColumns(int[][] matrix) {
|
||||
int rows = matrix.length;
|
||||
int cols = matrix[0].length;
|
||||
Integer[] indices = new Integer[cols];
|
||||
for (int i = 0; i < cols; i++)
|
||||
indices[i] = i;
|
||||
|
||||
Arrays.sort(indices, (a, b) -> Integer.compare(matrix[0][b], matrix[0][a]));
|
||||
int[][] sorted = new int[rows][cols];
|
||||
for (int i = 0; i < cols; i++) {
|
||||
for (int j = 0; j < rows; j++) {
|
||||
sorted[j][i] = matrix[j][indices[i]];
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < rows; i++)
|
||||
System.arraycopy(sorted[i], 0, matrix[i], 0, cols);
|
||||
}
|
||||
}
|
33
petrov_ilya_lab_1/src/ThreadPoolSorter.java
Normal file
33
petrov_ilya_lab_1/src/ThreadPoolSorter.java
Normal file
@ -0,0 +1,33 @@
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ThreadPoolSorter {
|
||||
public static void sort(int[][] matrix) throws InterruptedException {
|
||||
int cols = matrix[0].length;
|
||||
Integer[] indices = new Integer[cols];
|
||||
for (int i = 0; i < cols; i++)
|
||||
indices[i] = i;
|
||||
|
||||
Arrays.sort(indices, (a, b) -> Integer.compare(matrix[0][b], matrix[0][a]));
|
||||
|
||||
ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
|
||||
int[][] sorted = new int[matrix.length][cols];
|
||||
|
||||
for (int i = 0; i < cols; i++) {
|
||||
final int colIndex = i;
|
||||
executor.submit(() -> {
|
||||
for (int row = 0; row < matrix.length; row++) {
|
||||
sorted[row][colIndex] = matrix[row][indices[colIndex]];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
executor.shutdown();
|
||||
executor.awaitTermination(1, TimeUnit.HOURS);
|
||||
|
||||
for (int i = 0; i < matrix.length; i++)
|
||||
System.arraycopy(sorted[i], 0, matrix[i], 0, cols);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user