我有两个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
已挂钩到InputStream
,使用Scanner
(已正确配置)在数据到达时读取数据没有问题。
在这里,通过在记事本中刷新文件,我可以看到数据在生成时正确写入。但是当使用文件而不是InputStream时,永远不会到达if ( parseDataBundle()) {
行。
我做错了什么? Processor
似乎拥有文件资源,因为我无法在运行时删除它。我的直觉认为这可能与滥用并发性有关。
答案 0 :(得分: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;
}
这种方法的好处在于,它可以调整到获得消息的速率。
答案 1 :(得分:0)
Java NIO提供文件锁定支持。根据底层操作系统 - 您可以在写入完成后写入和释放锁定时获取文件的独占锁定。另一个进程可以尝试获取锁,如果有,则读取文件并释放它。轮询直到获得锁定。希望你明白这个主意。查看FileChannel#lock() API。