LR1.Tyutterin_Yakov_Z1411-3
.pdfМИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ федеральное государственное автономное образовательное учреждение высшего образования
«САНКТ-ПЕТЕРБУРГСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ АЭРОКОСМИЧЕСКОГО ПРИБОРОСТРОЕНИЯ»
ИНСТИТУТ НЕПРЕРЫВНОГО И ДИСТАНЦИОННОГО ОБРАЗОВАНИЯ
КАФЕДРА ПРИКЛАДНОЙ ИНФОРМАТИКИ
ОЦЕНКА
ПРЕПОДАВАТЕЛЬ
Канд. техн. наук |
|
С. А. Чернышев |
должность, уч. степень, звание |
подпись, дата |
инициалы, фамилия |
ОТЧЕТ О ЛАБОРАТОРНОЙ РАБОТЕ №1
Потоки
по дисциплине: Технологии программирования
РАБОТУ ВЫПОЛНИЛ |
|
|
|
|
|
СТУДЕНТ гр. № |
Z1411 |
|
|
Я. Н. Тюттерин |
|
|
|
|
|
|
|
|
номер группы |
подпись, дата |
|
инициалы, фамилия |
|
Студенческий билет № |
2022/4886 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Санкт-Петербург 2024
Лабораторная работа № 1. Потоки
Цель работы: познакомиться с основными способами работы с потоками.
Вариант 18.
Задание 1: Напишите программу, которая осуществляет чтение данных из файла в одном потоке и запись этих данных в другом потоке в файл. Названия файлов должны отличаться.
import java.io.*;
import java.nio.charset.StandardCharsets; import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
public class Main {
public static void main(String[] args) throws InterruptedException { new Main().run();
}
private void run() throws InterruptedException { String fileRead = "resources/text.txt"; //Количество строк в файле
AtomicInteger count = new AtomicInteger(countLines(fileRead)); //Счетчик для сигнала о корректном выполнении потоков
final CountDownLatch latch = new CountDownLatch(count.get());
final ExecutorService executorService = Executors.newFixedThreadPool(2);
//Потокобезопасная очередь
final ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<>();
//Поток чтения
Runnable reader = () -> {
try (BufferedReader br = new BufferedReader(new FileReader(fileRead, StandardCharsets.UTF_8))) {
while (br.ready()) {
//Чтобы избежать пустой строки в конце файла if (count.decrementAndGet() != 0) {
queue.add(br.readLine().concat("\n")); } else {
queue.add(br.readLine());
}
}
} catch (IOException ex) {
throw new RuntimeException("Что-то пошло не так", ex);
}
};
final String fileOut = "resources/text-out.txt";
//Поток записи
Runnable writer = () -> {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(fileOut, StandardCharsets.UTF_8))) {
final int batchSize = 50; int countLine = 0;
do {
if (!queue.isEmpty()) { bw.append(queue.poll());
if (batchSize == ++countLine) { bw.flush();
countLine = 0;
}
latch.countDown();
}
//Проверяем, что счетчик не стал равен 0, что сигнализирует об
окончании файла
} while (latch.getCount() != 0);
if (countLine != 0) { bw.flush();
}
} catch (IOException ex) {
throw new RuntimeException("Что-то пошло не так", ex);
}
};
//Запуск потока чтения
executorService.submit(reader); System.out.println("Hello"); //Запуск потока записи executorService.submit(writer); System.out.println("Hello");
latch.await();
executorService.shutdown();
}
//Метод подсчета строк в файле
private static int countLines(String filename) {
try (InputStream is = new BufferedInputStream(new FileInputStream(filename)))
{
byte[] c = new byte[1024];
int readChars = is.read(c); if (readChars == -1) {
// bail out if nothing to read return 0;
}
// make it easy for the optimizer to tune this loop int count = 0;
while (readChars == 1024) {
for (int i = 0; i < 1024; ) { if (c[i++] == '\n') {
++count;
}
}
readChars = is.read(c);
}
// count remaining characters while (readChars != -1) {
for (int i = 0; i < readChars; ++i) { if (c[i] == '\n') {
++count;
}
}
readChars = is.read(c);
}
return count == 0 ? 1 : count + 1; } catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
Наполнение файла имеет подобный вид:
Результат выполнения:
Задание 8: Напишите приложение для нахождения с использованием трех потоков значения по задаваемому диапазону элементов списка. Потоки должны полностью перекрывать длину списка.
import java.util.*;
import java.util.concurrent.*; import java.util.stream.Stream;
public class Main {
public static void main(String[] args) throws InterruptedException { Scanner scanner = new Scanner(System.in); System.out.println("Какую подстроку ищем?");
String findSubLine = scanner.next(); System.out.println("С какого индекса ищем"); int start = scanner.nextInt(); System.out.println("По какой индекс ищем"); int end = scanner.nextInt();
//Генерируем список строк в количестве end + 1(В будущем можно заменить на другой источник данных)
final List<String> data = Stream.generate(() -> UUID.randomUUID().toString().concat(UUID.randomUUID().toString())).limit(end + 1).toList();
new Main().run(findSubLine, start, end, data);
}
private void run(String findSubLine, int start, int end, List<String> data) throws InterruptedException {
final ExecutorService executorService = Executors.newFixedThreadPool(3); //Общее количество значений, которое требуется обработать
int count = end - start;
//"Счетчик", равенство = 0 будет ожидаться для корректного завершения выполнения
final CountDownLatch latch = new CountDownLatch(count);
final ConcurrentMap<Integer, String> strByIndex = new ConcurrentHashMap<>();
//Получаем размер партиции final int partition = count / 3;
final List<Runnable> tasks = new ArrayList<>(3); for (; start < end; start += (partition + 1)) {
//Вычисляем значение окончания партиции(учитывается, что на равные части деление может быть не возможно)
int endInclusive = Math.min(start + partition, end); final int finalStart = start;
//Заполняем список потоков tasks.add(() -> {
for (int i = finalStart; i <= endInclusive; i++) { final String line = data.get(i);
if (line.contains(findSubLine)) { strByIndex.put(i, line);
}
latch.countDown();
}
});
}
//Запускаем все созданные потоки
tasks.forEach(executorService::submit);
//Ждем, пока счетчик не станет 0
latch.await();
executorService.shutdown();
System.out.println(strByIndex);
}
}