forked from sevastyan_b/SSPR_25
zubkova_sofya_lab_1_is ready
This commit is contained in:
93
zubkova_sofya_lab_1/readme.md
Normal file
93
zubkova_sofya_lab_1/readme.md
Normal file
@@ -0,0 +1,93 @@
|
||||
# Лабораторная работа №1
|
||||
|
||||
Разработка многопоточного приложения с использованием Java Concurrency согласно варианту задания.
|
||||
|
||||
**Необходимо:**
|
||||
1. Разработать однопоточный вариант алгоритма и замерить время его работы.
|
||||
2. Разработать параллельный вариант алгоритма с использованием ThreadPoolExecutor и замерить время его работы
|
||||
3. Разработать параллельный вариант алгоритма с использованием ForkJoinPoll и замерить время его работы.
|
||||
Массив генерируется до работы всех вариантов алгоритмов. Все три алгоритма обрабатывают три одинаковых массива.
|
||||
|
||||
|
||||
## Вариант 12.
|
||||
Определить среднее арифметическое элементов матрицы ниже главной
|
||||
диагонали.
|
||||
|
||||
### Запуск лаборатороной работы:
|
||||
1. Компиляция программы осуществляется с помощью команды:
|
||||
> javac Main.java
|
||||
|
||||
2. Запуск скомпилированного класса:
|
||||
> java Main
|
||||
|
||||
### Использованные технологии:
|
||||
- Пакет `java.util.concurrent` предоставляет мощные инструменты для работы с многопоточностью и параллельными вычислениями
|
||||
- `ExecutorService` и `Executors` используются для управления пулами потоков и выполнения задач
|
||||
- `ThreadPoolExecutor` - в этом подходе используется пул потоков для параллельного вычисления суммы элементов матрицы. Матрица разбивается на части, и каждая часть обрабатывается отдельным потоком.
|
||||
- `ForkJoinPool` — специализированный пул потоков, предназначенный для выполнения задач, которые могут быть рекурсивно разбиты на более мелкие подзадачи (fork), а затем объединены (join).
|
||||
### Как работает программа:
|
||||
1. Происходит генерация массива размером = size в классе `Main.java`
|
||||
```
|
||||
public class Main {
|
||||
public static void main(String[] args) throws InterruptedException, ExecutionException {
|
||||
int size = 1000; // size matrix
|
||||
int[][] matrix = generateMatrix(size);
|
||||
```
|
||||
Метод для генерации массива:
|
||||
```
|
||||
private static int[][] generateMatrix(int size) {
|
||||
int[][] matrix = new int[size][size];
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < size; i++) {
|
||||
for (int j = 0; j < size; j++) {
|
||||
matrix[i][j] = random.nextInt(1000);
|
||||
}
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
```
|
||||
2. Создание трех копий исходного массива.
|
||||
3. Происходит обработка массива с помощью однопоточного варианта алгоритма ( класс SingleThreadedAverage).
|
||||
4. Класс ThreadPoolAverage обрабатывает матрицу с использованием пула потоков создается пул потоков (задается количество потоков = 4), а каждая строка матрицы обрабатывается в отдельном потоке.
|
||||
5. Класс ForkJoinAverage обрабатывает матрицу с использованием ForkJoinPool и рекурсивного разделения задачи: если блок большой, он разделяется на две части, и каждая часть обрабатывается рекурсивно.
|
||||
6. Происходит замер времени работы всех алгоритмов в классе `Main.java`:
|
||||
```
|
||||
// SingleThreaded algorithm
|
||||
long startTime = System.nanoTime();
|
||||
double singleThreadedResult = SingleThreadedAverage.calculate(matrix);
|
||||
long endTime = System.nanoTime();
|
||||
System.out.println("Result: " + singleThreadedResult);
|
||||
System.out.println("Single-threaded time: " + (endTime - startTime) / 1_000_000 + " ms");
|
||||
|
||||
// ThreadPoolExecutor algorithm
|
||||
startTime = System.nanoTime();
|
||||
double threadPoolResult = ThreadPoolAverage.calculate(matrix, 4);
|
||||
endTime = System.nanoTime();
|
||||
System.out.println("ThreadPoolExecutor time: " + (endTime - startTime) / 1_000_000 + " ms");
|
||||
|
||||
// ForkJoinPool algorithm
|
||||
startTime = System.nanoTime();
|
||||
double forkJoinResult = ForkJoinAverage.calculate(matrix);
|
||||
endTime = System.nanoTime();
|
||||
System.out.println("ForkJoinPool time: " + (endTime - startTime) / 1_000_000 + " ms");
|
||||
```
|
||||
### Тесты:
|
||||
- при size = 1000:
|
||||
Result: 498.8887907907908
|
||||
Single-threaded time: 4 ms
|
||||
ThreadPoolExecutor time: 104 ms
|
||||
ForkJoinPool time: 42 ms
|
||||
|
||||
Result: 499.8382882882883
|
||||
Single-threaded time: 1 ms
|
||||
ThreadPoolExecutor time: 35 ms
|
||||
ForkJoinPool time: 15 ms
|
||||
|
||||
- при size = 10000:
|
||||
Result: 499.5273448344835
|
||||
Single-threaded time: 26 ms
|
||||
ThreadPoolExecutor time: 42 ms
|
||||
ForkJoinPool time: 18 ms
|
||||
|
||||
## Вывод:
|
||||
При небольших размерах матрицы лучше использовать однопоточный вариант алгоритма, так как он дает лучший показатель времени. Однако, если размер генерируемой матрицы большой, то нужно использовать ForkJoinPool. А ThreadPoolExecutor - самый медленный.
|
||||
43
zubkova_sofya_lab_1/src/ForkJoinAverage.java
Normal file
43
zubkova_sofya_lab_1/src/ForkJoinAverage.java
Normal file
@@ -0,0 +1,43 @@
|
||||
import java.util.concurrent.RecursiveTask;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
public class ForkJoinAverage {
|
||||
private static class AverageTask extends RecursiveTask<Long> {
|
||||
private final int[][] matrix;
|
||||
private final int startRow;
|
||||
private final int endRow;
|
||||
|
||||
AverageTask(int[][] matrix, int startRow, int endRow) {
|
||||
this.matrix = matrix;
|
||||
this.startRow = startRow;
|
||||
this.endRow = endRow;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Long compute() {
|
||||
if (endRow - startRow <= 10) {
|
||||
long sum = 0;
|
||||
for (int i = startRow; i < endRow; i++) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
sum += matrix[i][j];
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
} else {
|
||||
int mid = (startRow + endRow) / 2;
|
||||
AverageTask left = new AverageTask(matrix, startRow, mid);
|
||||
AverageTask right = new AverageTask(matrix, mid, endRow);
|
||||
left.fork();
|
||||
long rightResult = right.compute();
|
||||
long leftResult = left.join();
|
||||
return leftResult + rightResult;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static double calculate(int[][] matrix) {
|
||||
ForkJoinPool pool = new ForkJoinPool();
|
||||
long totalSum = pool.invoke(new AverageTask(matrix, 0, matrix.length));
|
||||
int totalCount = matrix.length * (matrix.length - 1) / 2;
|
||||
return (double) totalSum / totalCount;
|
||||
}
|
||||
}
|
||||
41
zubkova_sofya_lab_1/src/Main.java
Normal file
41
zubkova_sofya_lab_1/src/Main.java
Normal file
@@ -0,0 +1,41 @@
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.Random;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) throws InterruptedException, ExecutionException {
|
||||
int size = 10000; // size matrix
|
||||
int[][] matrix = generateMatrix(size);
|
||||
|
||||
// SingleThreaded algorithm
|
||||
long startTime = System.nanoTime();
|
||||
double singleThreadedResult = SingleThreadedAverage.calculate(matrix);
|
||||
long endTime = System.nanoTime();
|
||||
System.out.println("Single-threaded result: " + singleThreadedResult);
|
||||
System.out.println("Single-threaded time: " + (endTime - startTime) / 1_000_000 + " ms");
|
||||
|
||||
// ThreadPoolExecutor algorithm
|
||||
startTime = System.nanoTime();
|
||||
double threadPoolResult = ThreadPoolAverage.calculate(matrix, 4);
|
||||
endTime = System.nanoTime();
|
||||
//System.out.println("ThreadPool result: " + threadPoolResult);
|
||||
System.out.println("ThreadPoolExecutor time: " + (endTime - startTime) / 1_000_000 + " ms");
|
||||
|
||||
// ForkJoinPool algorithm
|
||||
startTime = System.nanoTime();
|
||||
double forkJoinResult = ForkJoinAverage.calculate(matrix);
|
||||
endTime = System.nanoTime();
|
||||
//System.out.println("ForkJoin result: " + forkJoinResult);
|
||||
System.out.println("ForkJoinPool time: " + (endTime - startTime) / 1_000_000 + " ms");
|
||||
|
||||
}
|
||||
private static int[][] generateMatrix(int size) {
|
||||
int[][] matrix = new int[size][size];
|
||||
Random random = new Random();
|
||||
for (int i = 0; i < size; i++) {
|
||||
for (int j = 0; j < size; j++) {
|
||||
matrix[i][j] = random.nextInt(1000);
|
||||
}
|
||||
}
|
||||
return matrix;
|
||||
}
|
||||
}
|
||||
15
zubkova_sofya_lab_1/src/SingleThreadedAverage.java
Normal file
15
zubkova_sofya_lab_1/src/SingleThreadedAverage.java
Normal file
@@ -0,0 +1,15 @@
|
||||
public class SingleThreadedAverage {
|
||||
public static double calculate(int[][] matrix) {
|
||||
long sum = 0;
|
||||
int count = 0;
|
||||
int size = matrix.length;
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
sum += matrix[i][j];
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return (double) sum / count;
|
||||
}
|
||||
38
zubkova_sofya_lab_1/src/ThreadPoolAverage.java
Normal file
38
zubkova_sofya_lab_1/src/ThreadPoolAverage.java
Normal file
@@ -0,0 +1,38 @@
|
||||
import java.util.concurrent.*;
|
||||
public class ThreadPoolAverage {
|
||||
public static double calculate(int[][] matrix, int numThreads) throws InterruptedException, ExecutionException {
|
||||
ExecutorService executor = Executors.newFixedThreadPool(numThreads);
|
||||
int size = matrix.length;
|
||||
int chunkSize = size / numThreads;
|
||||
Future<Long>[] futures = new Future[numThreads];
|
||||
int[] counts = new int[numThreads];
|
||||
|
||||
for (int t = 0; t < numThreads; t++) {
|
||||
final int startRow = t * chunkSize;
|
||||
final int endRow = (t == numThreads - 1) ? size : startRow + chunkSize;
|
||||
final int threadIndex = t;
|
||||
futures[t] = executor.submit(() -> {
|
||||
long localSum = 0;
|
||||
int localCount = 0;
|
||||
for (int i = startRow; i < endRow; i++) {
|
||||
for (int j = 0; j < i; j++) {
|
||||
localSum += matrix[i][j];
|
||||
localCount++;
|
||||
}
|
||||
}
|
||||
counts[threadIndex] = localCount;
|
||||
return localSum;
|
||||
});
|
||||
}
|
||||
|
||||
long totalSum = 0;
|
||||
int totalCount = 0;
|
||||
for (int t = 0; t < numThreads; t++) {
|
||||
totalSum += futures[t].get();
|
||||
totalCount += counts[t];
|
||||
}
|
||||
|
||||
executor.shutdown();
|
||||
return (double) totalSum / totalCount;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user