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,我也像你一样做了一些测试。这是可能发生的。(永无止境。)