1

我有两个 Java 进程,Processor并且Simulator. Simulator每 5 秒写入规定的File X数据记录(10 行文本)。持续读取此文件,Processor等待令牌指示有效记录。代码是这样的(对文件名进行了一些替换):

Simulator中,每 5 秒:

FileWriter fileWriter = new FileWriter(DATA_FILE, true);
BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
bufferedWriter.write(DATA);
bufferedWriter.close();

Processor中,不断地:

mScanner = new Scanner(new BufferedReader(
        new FileReader(DATA_FILE)));
mScanner.useLocale(Locale.UK);

while (true) {              
    while (mScanner.hasNextLine()) {
    // Parse the data bundle.
    if (parseDataBundle()) {
            ...
        }
    }
}

以前,Processor连接到 an并且使用(适当配置)在数据到达时读取数据InputStream没有问题。Scanner

在这里,我可以看到通过在记事本中刷新文件生成数据时正在正确写入数据。但是当使用文件而不是 InputStream 时,if ( parseDataBundle()) {永远不会到达该行。

我究竟做错了什么?似乎拥有Processor文件资源,因为我无法在它运行时删除它。我的直觉认为这可能与滥用并发有关。

4

2 回答 2

2

我会说这是对文件的滥用。文件不是为消息传递而设计的。一旦你到达文件的末尾,就是它。避免这种情况的唯一方法是确保仅在知道有更多数据时才阅读(通过检查长度)这在使用文本时更加复杂。

您可以使用带有文本的文件,但这很棘手。您必须有一个线程轮询文件大小,并且当它发生变化时,只读取添加的字节(而不是更多)。这可以写入管道。您的阅读线程可以使用 InputStreamReader 和 BufferedReader 从管道中读取。


要改变轮询间隔,您可以使用不断升级的睡眠间隔,例如

long lastSize = 
int maxSleep = 5000, sleep = 200;
while(!Thread.currentThread().isInterrupted()) {
     long size = file.length();
     if (size > lastSize) {
        copyData(size - lastSize);
        lastSize = size;
        sleep = 200;
     } else {
        Thread.sleep(sleep);
        sleep += 200;
        if (sleep > maxSleep)
            sleep = maxSleep;
}

这种方法的好处是它的睡眠时间可以根据它获取消息的速率进行调整。

于 2013-07-19T12:14:28.267 回答
0

Java NIO 提供文件锁定支持。根据底层操作系统 - 您可以在写入时获得文件的排他锁,并在写入完成后释放锁。另一个进程可以尝试获取锁,如果它获得,则读取文件并释放它。轮询直到获得锁定。希望你能明白。查看FileChannel#lock() API。

于 2013-07-19T13:04:04.163 回答