2025-02-27 20:25:10 +04:00

183 lines
8.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Лабораторная работа №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 показал наименьшее время выполнения, потому что он эффективно распределяет задачи между несколькими потоками, уменьшая время ожидания на обработку каждого столбца матрицы.
В целом использование потоков ускоряет выполнение, так как позволяет параллельно обрабатывать несколько частей данных, в отличие от последовательной обработки без потоков.