Чтение файла с помощью BufferReader при записи нескольких потоков в файл

#java #multithreading #file #thread-safety

#java #многопоточность #файл #потокобезопасность

Вопрос:

Все, я пытаюсь прочитать файл, который будет записан несколькими потоками, я собираюсь использовать BufferedReader для чтения этого файла в потоке.

Код выглядит следующим образом.

 FileReader reader = new FileReader(file);
BufferedReader br = new BufferedReader(reader);
String detail;
while ((detail =br.readLine()) != null)
{
   ...
}
  

В настоящее время, похоже, работает нормально. Но у меня есть несколько вопросов по этому поводу.
Если вопрос звучит глупо. пожалуйста, не смейтесь надо мной. Спасибо.

Возможно ли, что цикл никогда не прерывался? потому что другие потоки записывают в файл.Так что, возможно, readLine() может никогда не возвращать значение null?

Обновлено

Допустим, есть 3 потока (T1, T2, T3).

T1 и T2 являются записывающими.

T3 — это reader.

Код выполняется в следующей последовательности.

1. Номер текущей строки файла равен 100.

2.T1 записать строку в файл.(количество строк файла увеличивается до 101)

3.T3 считывает последнюю строку файла (101). следующее чтение получит значение null.

4.T2 добавьте строку в файл.(количество строк файла увеличивается до 102)

5.T3 прочитайте еще раз….(Возвращает ли он значение null или нет? потому что T2 просто добавил новую строку в файл перед повторным чтением T3.)

Пожалуйста, помогите просмотреть его. заранее спасибо.

Комментарии:

1. Если считыватель читает быстрее, чем записывающие устройства, в конечном итоге он дойдет до конца файла, а затем вернет значение null. Если нет, то это завершится, когда в вашей файловой системе закончится свободное место, и записи прекратятся с помощью исключения IOException

2. @Pablo Я просто не уверен, может ли произойти то, о чем я сказал. Это похоже на проблему гонки? Спасибо

3. Для имитации сценария вы можете установить приоритет потока или время ожидания

4. Все ли эти потоки находятся в одной JVM? Если это так, зачем использовать неуклюжий и подверженный ошибкам подход к файлу вместо чего-то вроде параллельной очереди?

5. Кажется, было бы проще написать свою собственную реализацию регистратора.

Ответ №1:

Да, возможно, что цикл никогда не закончится (по крайней мере, пока у вас не закончится память). Вот некоторый код, подтверждающий это:

 public class test {

    public static void main(String[] args) {
// start thread to write to file
        new Thread(new Runnable() {
            @Override
            public void run() {
                FileWriter writer;
                try {
                    int i = 1;
                    writer = new FileWriter("D:\text.txt");
                    writer.append("line"  i     "n");
                    writer.flush();
                    while (true)
                    {
                        writer.append("line"  i     "n");
                        writer.flush();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }).start();

        try {
            Thread.sleep(500);
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        // start thread to read file
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    FileReader reader = new FileReader("D:\text.txt");
                    BufferedReader br = new BufferedReader(reader);
                    String detail;
                    while ((detail =br.readLine()) != null)
                    {
                        System.out.println(detail);
                    }
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }
        }).start();

    }
}
  

Комментарии:

1. Верно, я также провел несколько тестов, как и вы. Это может произойти. (никогда не заканчивается.)

Ответ №2:

Я провел для этого некоторый эксперимент.

Один eclipse запускает программу как writer .

 public class Main {

    private static Logger log = Logger.getLogger(Main.class);

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        PropertyConfigurator.configure("log4j.properties");
        log.warn("Test test test  ");
    }
}
  

Другой eclipse запускает программу как reader.

 public class Main {

    /**
     * @param args
     * @throws IOException 
     */
    public static void main(String[] args) throws IOException {
        // TODO Auto-generated method stub

        StringBuffer intiLine = new StringBuffer("");
        FileReader reader = new FileReader("D:\logs\notify-subscription.log");
        BufferedReader br = new BufferedReader(reader);
        String detail;
        while ((detail =br.readLine()) != null)//debug and set breakpoint here
        {
            System.out.println(detail);
        }
    }
}
  

прежде чем я начал их тестировать. Исходное содержимое файла журнала пустое.
Сначала я запустил программу чтения. результат br.readLine() должен быть нулевым. Но я установил точку останова в строке кода while ((detail =br.readLine()) != null) run, перед ее запуском я запустил программу записи. Итак, файл содержит test test test . и br.readLine() не будет нулевым.

Ответ №3:

Вы абсолютно правы.Также существует вероятность взаимоблокировки, если вы продолжаете создавать потоки для записи содержимого в файл.Поскольку, если потоки продолжают записывать в файл, не будет никаких шансов выйти из цикла, он переходит в бесконечное состояние

Комментарии:

1. Но дисковое пространство не бесконечно, авторы не могут писать вечно

2. Бесконечный цикл не является тупиковой ситуацией.

3. ДА. вы правы. Но я считаю, что это может повлиять на сценарии ожидания запроса @Pablo