观察者模式适合文件监控?

时间:2013-02-07 08:52:25

标签: java algorithm design-patterns

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

我目前正在使用它,但似乎有一种我无法解释的异常现象。基本上,我创建了一个名为FileMonitor的类,它有一个触发的计时器,它迭代一个独特文件列表,寻找一个改变的“最后修改日期”。

找到它后,会迭代一个监听器列表来查找匹配的文件,就是这样 fileChanged事件被通知。然后它开始处理文件中添加的行。

所以让我的问题更简洁:

  1. 观察者模式是否适合我想做的事情? (目前 我每个文件都有一个监听器)
  2. 如果存在多个文件,是否存在'并发问题'的可能性 显示器?
  3. 由于

4 个答案:

答案 0 :(得分:4)

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

来自官方文件:

  

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

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

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

您必须使用FileAlterationMonitor注册oberver。继续使用相同的文档:

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

其中interval是检查文件系统之间等待的时间(以毫秒为单位)。

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

答案 1 :(得分:3)

Java 7引入了WatchService,它监视已注册对象的更改和事件。

  

Watchable对象通过调用它来注册监视服务   注册方法,返回一个WatchKey来表示注册。   当检测到对象的事件时,将发信号通知密钥,如果是   目前尚未发出信号,它排队等待观看服务   可以由调用poll或使用方法的消费者检索   检索密钥和处理事件。一旦事件被处理完毕   消费者调用密钥的重置方法来重置密钥   允许密钥通过其他事件发出信号并重新排队。

     

文件系统可以比检索事件更快地报告事件   已处理并且实施可能会对此施加未指定的限制   它可能累积的事件数量。哪里有实施   故意丢弃事件然后它安排密钥的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());
    }
}

参考 - link

答案 2 :(得分:3)

  

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

是的。

  

鉴于存在“并发问题”,是否存在任何可能性   要监控多个文件?

如果您有多个线程删除并将侦听器添加到由ArrayList备份的列表,则会冒ConcurrentModificationException的风险。请改用CopyOnWriteArrayList

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

答案 3 :(得分:0)

我建议去NIO

和文件观察程序服务 - Watching File For Changes