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