3

我很想知道观察者模式是否是实现代码以监视日志文件及其更改的正确方法?

我目前正在使用它,但似乎有一个我无法解释的异常情况。基本上,我创建了一个名为 FileMonitor 的类,它有一个触发的计时器,它迭代一个唯一文件列表,以查找更改的“lastmodified date”。

找到它后,将遍历Listeners 列表以找到匹配的文件,并通知它的fileChanged 事件。然后它开始处理文件中添加的行。

所以为了让我的问题更简洁:

  1. 观察者模式是否适合我想要做的事情?(目前我每个文件有一个监听器)
  2. 鉴于要监控的文件不止一个,是否存在“并发问题”的可能性?

谢谢

4

4 回答 4

5

Java 7 引入了WatchService哪些监视注册对象的更改和事件。

一个 Watchable 对象通过调用它的 register 方法注册到一个 watch 服务,返回一个 WatchKey 来表示注册。当检测到对象的事件时,会发出键信号,如果当前未发出信号,则将其排队到监视服务,以便调用 poll 或 take 方法以检索键和处理事件的消费者可以检索它。处理完事件后,消费者调用密钥的重置方法来重置密钥,这允许向密钥发出信号并与进一步的事件一起重新排队。

文件系统报告事件的速度可能比检索或处理事件的速度更快,并且实现可能对其可能累积的事件数量施加未指定的限制。如果实现故意丢弃事件,那么它会安排键的 pollEvents 方法返回事件类型为 OVERFLOW 的元素。消费者可以使用此事件作为触发器来重新检查对象的状态。

例子 -

Path myDir = Paths.get("D:/test");       

    try {
       WatchService watcher = myDir.getFileSystem().newWatchService();
       myDir.register(watcher, StandardWatchEventKind.ENTRY_CREATE, 
       StandardWatchEventKind.ENTRY_DELETE, StandardWatchEventKind.ENTRY_MODIFY);

       WatchKey watckKey = watcher.take();

       List<WatchEvent<?>> events = watckKey.pollEvents();
       for (WatchEvent event : events) {
            if (event.kind() == StandardWatchEventKind.ENTRY_CREATE) {
                System.out.println("Created: " + event.context().toString());
            }
            if (event.kind() == StandardWatchEventKind.ENTRY_DELETE) {
                System.out.println("Delete: " + event.context().toString());
            }
            if (event.kind() == StandardWatchEventKind.ENTRY_MODIFY) {
                System.out.println("Modify: " + event.context().toString());
            }
        }

    } catch (Exception e) {
        System.out.println("Error: " + e.toString());
    }
}

参考 -链接

于 2013-02-07T08:58:19.293 回答
4

如果您不想使用 Java 7,则可以使用Apache IO获得相同的行为。

来自官方文档:

FileAlterationObserver 表示根目录下文件的状态,检查文件系统并通知侦听器创建、更改或删除事件。

以下是如何添加侦听器以定义在此类事件发生时要执行的操作。

  File directory = new File(new File("."), "src");
  FileAlterationObserver observer = new FileAlterationObserver(directory);
  observer.addListener(...);
  observer.addListener(...);

您必须使用FileAlterationMonitor. 从相同的文档继续:

  long interval = ...
  FileAlterationMonitor monitor = new FileAlterationMonitor(interval);
  monitor.addObserver(observer);
  monitor.start();
  ...
  monitor.stop();

interval在文件系统检查之间等待的时间量(以毫秒为单位)在哪里。

查找org.apache.commons.io.monitor库中命名的包。

于 2013-02-07T09:09:04.777 回答
3

观察者模式是否适合我想要做的事情?(目前我每个文件有一个监听器)

是的,它确实。

鉴于要监控的文件不止一个,是否存在“并发问题”的可能性?

如果您有多个线程将侦听器删除并添加到由 an 备份的列表中,ArrayList您将面临ConcurrentModificationException. 改用 a CopyOnWriteArrayList

IIRC Effective java 有一篇文章,其中包含一个很好的例子。

于 2013-02-07T09:00:53.653 回答
0

我建议去NIO

和 File Watcher 服务 -观察文件的变化

于 2013-02-07T08:57:46.507 回答