Форум программистов, компьютерный форум, киберфорум
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.76/25: Рейтинг темы: голосов - 25, средняя оценка - 4.76
1 / 1 / 1
Регистрация: 11.07.2018
Сообщений: 96
1

Многопоточность и работа с файлами

23.10.2019, 23:36. Показов 4738. Ответов 15
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Здравствуйте. Поставили задачу, реализовать приложение у которого:

Имеется 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

Исходный код основного класса
Java
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 поток
Java
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("Не удалось открыть файл!");
        }
    }
}
Исходный код класса, отвечающий за 2 поток
Java
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() {
        List<Integer> 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());
        }
    }
}
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
23.10.2019, 23:36
Ответы с готовыми решениями:

Многопоточность при работе с файлами
Доброй ночи! Написал код для сравнения двух файлов: string text, text2; ...

Работа с файлами , хотелось бы с windows system файлами
всем привет, нужна интересная идея по программированию, работа с файлами , хотелось бы с windows...

Многопоточность и работа с COM-портом
Добрый день. Необходимо реализовать программу, которая будет непрерывно читать из...

Многопоточность и работа с прокси
здравствуйте, решил написать простенькую программу с потоками и работай через прокси(HTTP/S,...

15
1022 / 562 / 185
Регистрация: 18.08.2013
Сообщений: 2,026
Записей в блоге: 2
24.10.2019, 05:48 2
Чувак, зачем ты у них sleep вызываешь? Их надо просто запустить и забыть про них

Добавлено через 1 минуту
И оборачивай их в Thread
0
1 / 1 / 1
Регистрация: 11.07.2018
Сообщений: 96
24.10.2019, 15:52  [ТС] 3
sleep вызывается, чтобы в файл записывались значения через каждую 1 с., а не через каждые микросекунды. Что значит оборачивать их в Thread? Разве Runnable не производит этого?
0
1022 / 562 / 185
Регистрация: 18.08.2013
Сообщений: 2,026
Записей в блоге: 2
24.10.2019, 16:02 4
Цитата Сообщение от W014ara Посмотреть сообщение
Разве Runnable не производит этого?
Нет. Нельзя вручную вызывать метод run у Runnable, надо оборачивать в Thread. Цикл чтения и записи сделай внутри Runnable и если надо, то добавь туда sleep()
0
Эксперт Java
3639 / 2971 / 918
Регистрация: 05.07.2013
Сообщений: 14,220
24.10.2019, 16:12 5
Цитата Сообщение от Gungala Посмотреть сообщение
Нельзя вручную вызывать метод run у Runnable
можно, кто ж мешает. Просто результат другой.
0
1 / 1 / 1
Регистрация: 11.07.2018
Сообщений: 96
25.10.2019, 00:43  [ТС] 6
Gungala
Вы имеете ввиду сделать такую конструкцию?
Java
1
2
First_Thread first_thread = new First_Thread();
new Thread(first_thread).start();
0
1022 / 562 / 185
Регистрация: 18.08.2013
Сообщений: 2,026
Записей в блоге: 2
25.10.2019, 05:58 7
Ага
0
1 / 1 / 1
Регистрация: 11.07.2018
Сообщений: 96
25.10.2019, 10:06  [ТС] 8
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 строки в файле, при этом не закрывая его?
0
1022 / 562 / 185
Регистрация: 18.08.2013
Сообщений: 2,026
Записей в блоге: 2
25.10.2019, 11:17 9
Как вариант
Java
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();
    }
}
0
1 / 1 / 1
Регистрация: 11.07.2018
Сообщений: 96
25.10.2019, 13:50  [ТС] 10
Gungala

Компилятор кричит на ошибку в строчке.
Java
1
try (Scanner in = new Scanner(Test.class.getResourceAsStream("text.txt"), "UTF-8"))
Не особо понимаю, файл вроде бы существует и первый поток записывает в него данные, но вот 2 поток уже кричит.
0
1022 / 562 / 185
Регистрация: 18.08.2013
Сообщений: 2,026
Записей в блоге: 2
25.10.2019, 15:31 11
Файл "text.txt" должен лежать в той же директории, что файл класса
0
1 / 1 / 1
Регистрация: 11.07.2018
Сообщений: 96
26.10.2019, 02:18  [ТС] 12
Gungala

Попытался сделать следующим образом:

Основной класс программы
Java
1
2
3
4
5
6
7
8
9
10
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();
    }
}

Класс, отвечающий за первый поток
Java
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 поток

Java
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 поток соответственно:

Java
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");
        }
    }
}
0
1022 / 562 / 185
Регистрация: 18.08.2013
Сообщений: 2,026
Записей в блоге: 2
26.10.2019, 11:05 13
Лучший ответ Сообщение было отмечено W014ara как решение

Решение

В общем, я потратил достаточно много времени, но так и не смог сделать ничего умного, поэтому пришлось делать то, что работает. При каждой итерации второй поток с самого начала читает файл. Стрёмненько, но иначе никак сделать у меня не вышло
Java
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");
        }
    }
}
1
1 / 1 / 1
Регистрация: 11.07.2018
Сообщений: 96
26.10.2019, 14:06  [ТС] 14
Gungala

Спасибо большое, да, отрабатывает именно так, как нужно.

Добавлено через 30 минут
Gungala

Единственное, хотел дополнительно спросить, как можно будет синхронизировать мои три потока?
Чтобы они отрабатывали именно в порядке 1 2 3, а не, например 1 3 2?
0
1022 / 562 / 185
Регистрация: 18.08.2013
Сообщений: 2,026
Записей в блоге: 2
26.10.2019, 15:29 15
Не совсем понимаю, зачем использовать многопоточность, если нужно последовательное выполнение. Не знаю, если честно, я сам в этом деле почти не имею опыта. Возможно, BlockingQueue подошла бы, погугли
0
1 / 1 / 1
Регистрация: 11.07.2018
Сообщений: 96
26.10.2019, 16:16  [ТС] 16
Понимаю, что можно обойтись без многопоточности, но так поставили задание. Спасибо за помощь, еще раз!
0
26.10.2019, 16:16
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
26.10.2019, 16:16
Помогаю со студенческими работами здесь

Многопоточность, не правильная работа с мютекосом. Что не так?
Добрый. Хочу чтобы разрешение (permission) устанавливалось только один раз каким-либо потоком, а...

Работа с файлами(Запись,чтение,работа с данными)
Здравствуйте, никак не могу осилить файлы... Для начала вот само задание: В справочной автовокзала...

Лабораторная работа №5. Работа с файлами и алгоритмы сортировки
1. Написать функцию Load для считывания из текстового файла (например, Workers.txt) информации о...

Работа с файлами, чтение/работа со строкой
Доброго времени суток. Начал работать с C++ Builder 6. Есть текстовый файл .txt с различными...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
16
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru