Java 当多线程写入文件时,使用BufferReader读取文件
总之,我试图读取一个将由多个线程写入的文件,我将使用Java 当多线程写入文件时,使用BufferReader读取文件,java,multithreading,file,thread-safety,Java,Multithreading,File,Thread Safety,总之,我试图读取一个将由多个线程写入的文件,我将使用BufferedReader在一个线程中读取该文件 代码如下所示 FileReader reader = new FileReader(file); BufferedReader br = new BufferedReader(reader); String detail; while ((detail =br.readLine()) != null) { ... } 目前看来效果不错。但我有一些问题。 如果这个问题听起来很傻。请不要嘲
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是读卡器
代码按以下顺序运行
1.当前文件行数为100
2.T1在文件中写入一行。(文件行增加到101)
3.T3读取文件的最后一行(101)。下一次读取将为空
4.T2在文件中追加一行。(文件行增加到102)
5.T3再次读取…(它是否返回null?因为T2在T3再次读取之前刚刚在文件中添加了新行。)
请帮助审阅。提前感谢。您完全正确。如果您继续创建线程将内容写入文件,也有可能出现死锁。因为如果线程继续写入文件,则不会有任何退出循环的机会,它将进入无限状态。是的,循环可能永远不会结束(至少在内存耗尽之前)。下面是一些代码来证明这一点:
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();
}
}
我做了一些实验 一个eclipse以编写器的身份运行程序
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以读卡器的身份运行该程序
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);
}
}
}
在我开始测试之前。原始日志文件内容为空。
我首先运行了reader程序。
br.readLine()
的结果应为空。但是我在((detail=br.readLine())!=null)运行时在代码行设置断点,在它运行之前,我运行了writer程序。因此,该文件包含test
。和br.readLine()
将不为空 如果读卡器的读取速度比写卡器的写入速度快,那么它最终将到达文件末尾,然后返回null。如果没有,那么当文件系统的可用空间用完并且写入程序停止时,它将结束IOException@Pablo我只是不确定我所说的情况是否会发生。听起来像是种族问题?感谢您模拟这个场景,您可以设置线程优先级或睡眠时间。所有这些线程都在同一个JVM中吗?如果是这样的话,为什么要使用笨拙且容易出错的文件方法,而不是像并发队列这样的方法呢?似乎编写自己的日志程序实现会更简单。但是磁盘空间不是无限的,写入程序无法编写forever无限循环不是死锁。是的。你是对的。但我相信这可能会影响请求超时的场景@PabloRight,我也像你一样做了一些测试。这是可能发生的。(永无止境。)