java - 如何从使用另一个线程不断追加的文件中读取数据?

标签 java multithreading synchronized

我遇到了一个问题“创建 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) {}
 }
}

任何帮助和更好的实现表示赞赏。 P.S:我使用了 volatile 以及 isAAlive() 但它不起作用。我认为问题出在 writer 的 while 循环中,其中读者运行的 boolean 变量更新为 false 没有反射(reflect)在读者中。 P.P.S:是的,我知道这是实现并发的低效方法,但我只是好奇这是否有效。 编辑:我已经根据 muradm 的建议更新了代码。仍然欢迎对代码的任何改进。(更新的代码在上面链接)

最佳答案

问题是您试图立即打开同一个文件。只是为了给你一个想法:

// 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(),那么编写器实际上是在读者开始 wait() 之前 notified() 。 IE。服务员将错过在 wait() 调用之前发生的通知。

关于java - 如何从使用另一个线程不断追加的文件中读取数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53799463/

相关文章:

html - 禁止自动播放同步到文本的html5音频

java - 使用同步(锁定对象) block 时,静态锁定对象是否需要是最终的?

java - 在 Java 中跟踪 websocket 连接的最佳实践

java - 使用 hasNextLine() 但仍然收到 java.util.NoSuchElementException : No line found

java - 如何使用 Anypoint Studio 从巨大的 csv 文件中删除重复记录并将其存储到 Mulesoft 的数据库中

java - 使用数据库时可以使用类型检查代码吗?

java - 这个变量需要声明为volatile吗?

android - 我的 android 应用程序有一个基于似乎损坏的 ASyncTask 的客户端套接字

java - Oracle ADF : Cannot convert 1 of type class java. math.BigDecimal 类 oracle.jbo.domain.Number

java - 为什么使用 long literal 计算需要更多时间?