Многопоточность и работа с файлами
Здравствуйте. Поставили задачу, реализовать приложение у которого:
Имеется 3 потока, а также 2 файла
1 поток записывает каждую секунду некоторое случайное число в файл journal_1.txt
2 поток просматривает каждую секунду файл journal_1.txt и записывает сумму последних двух записанных в этот файл чисел в файл journal_2.txt
3 поток просматривает каждую секунду файл journal_2.txt и записывает сумму последних двух записанных в этот файл в файл journal_1.txt
С потоками знаком плохо, потому возникли проблемы с реализацией. Попробовал сделать 3 класса под 3 потока, который как-то пытались реализовать поставленную задачу. Однако, пока что правильно отрабатывает лишь 1 поток. Второй класс некорректно забирает данные из файла journal_1.txt
Исходный код основного класса
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
package application; public class Threads_question { public static void main(String[] args) throws InterruptedException { First_Thread first_thread = new First_Thread(); Second_Thread second_thread = new Second_Thread(); Third_Thread third_thread = new Third_Thread(); while(true){ first_thread.run(); first_thread.sleep(); second_thread.run(); second_thread.sleep(); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
package application; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; public class First_Thread implements Runnable { private int num = 1; private int get_num(){ return this.num; } void sleep() throws InterruptedException { Thread.sleep(1000); } @Override public void run() { String filePath = "journal_1.txt"; String text = Integer.toString(get_num()); try { // System.out.println(num++); Files.write(Paths.get(filePath), text.getBytes(), StandardOpenOption.APPEND); } catch (Exception e){ System.out.println("Не удалось открыть файл!"); } } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
package application; import java.io.FileReader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.List; public class Second_Thread implements Runnable { void sleep() throws InterruptedException { Thread.sleep(1000); } @Override public void run() { ListInteger> num_list = new ArrayList<>(); String filePath = "journal_2.txt"; try(FileReader reader = new FileReader("journal_1.txt")) { // читаем посимвольно int c; int sum = 0; while((c = reader.read()) != -1){ num_list.add(Integer.parseInt((char) c + "")); for(int index = 0; index num_list.size(); ++index){ if(index % 2 != 0 ){ int rez = num_list.get(index) + num_list.get(index - 1); System.out.println(rez); String text = Integer.toString(rez); try { Files.write(Paths.get(filePath), text.getBytes(), StandardOpenOption.APPEND); } catch (Exception e){ System.out.println("Не удалось открыть файл!"); } } } } } catch(IOException ex){ System.out.println(ex.getMessage()); } } }
Многопоточность при работе с файлами
Доброй ночи! Написал код для сравнения двух файлов: string text, text2; .
Работа с файлами , хотелось бы с windows system файлами
всем привет, нужна интересная идея по программированию, работа с файлами , хотелось бы с windows.
Многопоточность и работа с COM-портом
Добрый день. Необходимо реализовать программу, которая будет непрерывно читать из.
Многопоточность и работа с прокси
здравствуйте, решил написать простенькую программу с потоками и работай через прокси(HTTP/S.
Чувак, зачем ты у них sleep вызываешь? Их надо просто запустить и забыть про них
Добавлено через 1 минуту
И оборачивай их в Thread
sleep вызывается, чтобы в файл записывались значения через каждую 1 с., а не через каждые микросекунды. Что значит оборачивать их в Thread? Разве Runnable не производит этого?
Сообщение от W014ara
Нет. Нельзя вручную вызывать метод run у Runnable, надо оборачивать в Thread. Цикл чтения и записи сделай внутри Runnable и если надо, то добавь туда sleep()
Сообщение от Gungala
First_Thread first_thread = new First_Thread(); new Thread(first_thread).start();
Gungala
Спасибо, теперь тогда вопрос по самой работе программы. Первый класс все хорошо делает, добавляет в journal_1.txt какие-то цифры каждую секунду. Проблема возникает со вторым классом (реализовывать 3-ий не было смысла, ибо он аналогичен, как я понял 2-ому, только проверять будет уже journal_2.txt). Каждый раз при отработке метода start у второго класса, он кидает полностью обновленный список в journal_1.txt
Например, 1 поток закинул в 1 файл цифры: 1 1 2 3
Второй поток выводит следующее:
2
2
3
2
3
5
Полагаю, что косяк в постоянном пересоздании ArrayList, но как решать подобный траб не понимаю. Есть ли способ, например, как-то достать именно последние 2 строки в файле, при этом не закрывая его?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
import java.io.*; import java.util.Random; import java.util.Scanner; import java.util.concurrent.ThreadLocalRandom; public class Test { public static void main(String[] args) { Thread first = new Thread(() -> { Random rand = ThreadLocalRandom.current(); String path = Test.class.getResource("text").getPath(); try (PrintWriter pw = new PrintWriter(new FileWriter(path, true), true)) { while (true) { pw.println(rand.nextInt(100)); Thread.sleep(1000); } } catch (IOException | InterruptedException e) { e.printStackTrace(); } }); Thread second = new Thread(() -> { int[] nums = new int[2]; int index = 0; try (Scanner in = new Scanner(Test.class.getResourceAsStream("text"), "UTF-8")) { while (true) { nums[index++] = in.nextInt(); if (index == 2) { index = 0; } System.out.println(nums[0] + nums[1]); Thread.sleep(1000); } } catch (InterruptedException e) { e.printStackTrace(); } }); first.start(); second.start(); } }
Компилятор кричит на ошибку в строчке.
try (Scanner in = new Scanner(Test.class.getResourceAsStream("text.txt"), "UTF-8"))
Не особо понимаю, файл вроде бы существует и первый поток записывает в него данные, но вот 2 поток уже кричит.
Попытался сделать следующим образом:
Основной класс программы
package application; public class Test { public static void main(String[] args) throws InterruptedException { First_Thread first_thread = new First_Thread(); Second_Thread second_thread = new Second_Thread(); new Thread(first_thread).start(); new Thread(second_thread).start(); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
package application; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.Random; import java.util.concurrent.ThreadLocalRandom; public class First_Thread implements Runnable { @Override public void run() { Random rand = ThreadLocalRandom.current(); String path = "text.txt"; try (PrintWriter pw = new PrintWriter(new FileWriter(path, true), true)) { while (true) { int digit = rand.nextInt(100); System.out.println(digit); pw.println(digit); Thread.sleep(1000); } } catch (IOException | InterruptedException e) { e.printStackTrace(); } } }
Класс, отвечающий за 2 поток
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
package application; import java.io.*; import java.nio.file.Paths; import java.util.Scanner; public class Second_Thread implements Runnable { @Override public void run() { String path = "text_1.txt"; int[] nums = new int[2]; int index = 0; try (Scanner in = new Scanner(Paths.get("text.txt"), "UTF-8")) { while (true) { nums[index++] = in.nextInt(); if (index == 2) { index = 0; } String digit = Integer.toString(nums[0] + nums[1]); System.out.println("Второй поток сложил числа: " + nums[0] + " и " + nums[1] + " - получил в результате число: " + digit); try (PrintWriter pw = new PrintWriter(new FileWriter(path, true), true)) { pw.println(digit); } catch (IOException e) { e.printStackTrace(); } Thread.sleep(1000); } } catch (InterruptedException | IOException e) { System.out.println("error"); } } }
Появились следующий проблемы:
1) Если делать класс 3, аналогичный классу 2, просто поменяв названия файлов, то возникает ошибка (когда оба файла пустые);
2) При повторном перезапуске программы 2 поток начинает суммировать все числа из файла text.txt заново, вместо того, чтобы продолжить просто вносить изменения.
Как можно решить данные проблемы?
Добавлено через 8 минут
Класс, отвечающий за 3 поток соответственно:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
package application; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.nio.file.Paths; import java.util.Scanner; public class Third_Thread implements Runnable { @Override public void run() { String path = "text.txt"; int[] nums = new int[2]; int index = 0; try (Scanner in = new Scanner(Paths.get("text_1.txt"), "UTF-8")) { while (true) { nums[index++] = in.nextInt(); if (index == 2) { index = 0; } String digit = Integer.toString(nums[0] + nums[1]); System.out.println("Третий поток сложил числа: " + nums[0] + " и " + nums[1] + " Получил в результате число: " + digit); Thread.sleep(1000); } } catch (InterruptedException | IOException e) { System.out.println("error"); } } }
Сообщение было отмечено W014ara как решение
Решение
В общем, я потратил достаточно много времени, но так и не смог сделать ничего умного, поэтому пришлось делать то, что работает. При каждой итерации второй поток с самого начала читает файл. Стрёмненько, но иначе никак сделать у меня не вышло
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; import java.util.Random; import java.util.Scanner; import java.util.concurrent.ThreadLocalRandom; public class Test { public static void main(String[] args) { First_Thread first_thread = new First_Thread(); Second_Thread second_thread = new Second_Thread(); Third_Thread third_thread = new Third_Thread(); new Thread(first_thread).start(); new Thread(second_thread).start(); //new Thread(third_thread).start(); } } class First_Thread implements Runnable { @Override public void run() { Random rand = ThreadLocalRandom.current(); String path = Test.class.getResource("text").getPath(); try (PrintWriter pw = new PrintWriter(new FileWriter(path, true), true)) { while (true) { int digit = rand.nextInt(100); System.out.println(digit); pw.println(digit); Thread.sleep(1000); } } catch (IOException | InterruptedException e) { e.printStackTrace(); } } } class Second_Thread implements Runnable { @Override public void run() { String path = Test.class.getResource("text1").getPath(); int[] nums = new int[2]; int index = 0; try (PrintWriter pw = new PrintWriter(new FileWriter(path, true), true)) { while (true) { try (Scanner in = new Scanner(Test.class.getResourceAsStream("text"), "UTF-8")) { while (in.hasNextInt()) { nums[index++] = in.nextInt(); if (index == 2) { index = 0; } } String digit = Integer.toString(nums[0] + nums[1]); System.out.println("Второй поток сложил числа: " + nums[0] + " и " + nums[1] + " - получил в результате число: " + digit); pw.println(digit); } Thread.sleep(1000); } } catch (InterruptedException | IOException e) { System.out.println("error"); } } }