Как прочитать данные из файла, который постоянно добавляется с помощью другого потока? - PullRequest
0 голосов
/ 16 декабря 2018

У меня проблема: «Создайте 2 потока, один будет записывать данные в файл (из строки, определенной в программе), а другой будет считывать данные из того же файла и отображать их на консоли».Вот моя реализация, но она застревает в бесконечном цикле

import java.io.* 
class ReaderWriter {
 int ch;
 FileInputStream fin;
 FileOutputStream fout;
 boolean rdrblocked = false;
 static volatile boolean running;
 static volatile boolean eof = false;
 String s = "This will end up in a file in the same order as it appears here or else we can conclude that there is some discrepancy related to some race condition stuff";
 byte b[] = s.getBytes();
 int length = b.length;

 void writer() throws Exception {
  fout = new FileOutputStream("Demo.txt");
  for (int i = 0; i < length; i++) {
   fout.write(b[i]);
   if (rdrblocked) {
    synchronized(this) {
     rdrblocked = false;
     notify();
    }
   }
  }
  eof = true;
  while (running) {
   synchronized(this) {
    rdrblocked = false;
    notify();
   }
  }
  fin.close();

 }

 void reader() throws Exception {
  running = true;
  fin = new FileInputStream("Demo.txt");
  if (fin.available() > 0) {
   while ((ch = fin.read()) != -1) {
    System.out.print((char) ch);
    while (fin.available() == 0 && !eof) {
     synchronized(this) {
      rdrblocked = true;
      wait();
     }
    }
   }
  }
  running = false;
  fin.close();
 }
}

class Writercall implements Runnable {
 Thread t;
 ReaderWriter obj;
 Writercall(ReaderWriter obj) {
  this.obj = obj;
  t = new Thread(this, "Reader");
  t.start();
 }
 public void run() {
  try {
   obj.writer();
  } catch (Exception e) {}
 }
}

class Readercall implements Runnable {
 Thread t;
 ReaderWriter obj;
 Readercall(ReaderWriter obj) {
  this.obj = obj;
  t = new Thread(this, "Writer");
  t.start();
 }
 public void run() {
  try {
   obj.reader();
  } catch (Exception e) {}
 }
}

class RWDemo {
 public static void main(String args[]) throws Exception {
  ReaderWriter obj1 = new ReaderWriter();
  Readercall r = new Readercall(obj1);
  Writercall w = new Writercall(obj1);
  try {
   r.t.join();
   w.t.join();
  } catch (Exception e) {}
 }
}

Любая помощь и лучшие реализации приветствуются.PS: я использовал volatile так же, как и isAAlive (), но он не работает. Проблема, которую я считаю, заключается в цикле писателя while, когда обновление логической переменной, выполняемой читателем до false, не отражается в читателе.PPS: Да, ребята, я знаю, что это неэффективный способ достижения параллелизма, но мне просто любопытно, сработает ли это.Изменить: Я обновил код в соответствии с предложениями muradm. Любые улучшения в коде по-прежнему приветствуются. (Обновленный код связан выше)

1 Ответ

0 голосов
/ 16 декабря 2018

Проблема в том, что вы пытаетесь открыть тот же файл мгновенно.Просто чтобы дать вам представление:

// omitted
void reader() throws Exception {
    // reader waits before writer notify
    // writer notifies reader to wake up
    synchronized (this) {
        rdrblocked = true;
        wait();
    }
    while (!new File("Demo.txt").exists() && running) {
        Thread.sleep(10);
    }
    fin = new FileInputStream("Demo.txt");
    if (fin.available() > 0) {
        while ((ch = fin.read()) != -1) {
            System.out.print((char) ch);
        }
    }
    // omitted

Т.е., так как файл не существует в начале, тогда и читатель, и писатель могут получить разные дескрипторы от ОС.Заставить читателя проверить, существует ли файл, и ждать его существования, но все же ...

Однако это не является хорошим решением.Ваша цель неясна:

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

Если за этим стоит реальная задача, вам нужно будет найти более сложное решение для обеспечения надежного чтения /запись из одного файла.Как RandomAccessFile или еще.

Кроме того, если вы работаете wait() и notify(), тогда wait() должно произойти до notify(), в противном случае, если вы wait() после данныхчитал из файла, затем писатель на самом деле notified(), прежде чем даже читатель начал wait().Т.е. официант пропустит уведомления, произошедшие до wait() звонка.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...