【问题标题】:Observer pattern Right for File Monitoring?观察者模式适合文件监控吗?
【发布时间】:2013-02-07 08:52:25
【问题描述】:

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

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

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

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

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

谢谢

【问题讨论】:

    标签: java algorithm design-patterns


    【解决方案1】:

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

    Watchable 对象通过调用其监视服务注册到监视服务 register 方法,返回一个 WatchKey 表示注册。 当检测到对象的事件时,会发出按键信号,并且如果 当前未发出信号,它将排队到 watch 服务,以便它 可以由调用 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());
        }
    }
    

    参考 - link

    【讨论】:

    • 谢谢 - 但遗憾的是我也使用 Java 6 因为我们现有的技术都在 6 上
    • 你可以使用 Apache VFS 与 java 6 完全相同的功能。
    【解决方案2】:

    如果您不想使用 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 的包。

    【讨论】:

      【解决方案3】:

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

      是的。

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

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

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

      【讨论】:

      • +1 因为 a.正确和 b。在不添加其他依赖项的情况下回答问题。
      【解决方案4】:

      我建议去NIO

      和 File Watcher 服务 - Watching File For Changes

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-20
        • 2023-04-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多