1. 概述

早在Java 7引入WatchService API之前,Apache Commons IO Monitoring库就已经解决了监控文件系统位置或目录变化的相同问题。

本文将探讨这两个API之间的差异。

2. Maven依赖

要使用Apache Commons IO,需要在pom.xml中添加以下依赖:

<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.15.1</version>
</dependency>

当然,WatchService是JDK的一部分,因此无需外部依赖。

3. 功能比较

3.1. 事件驱动处理

WatchService API由操作系统触发的文件系统变更事件驱动,这种方法避免了应用程序频繁地轮询文件系统以查找变化。

相比之下,Apache Commons IO Monitor库通过调用File类的listFiles()方法,以可配置的睡眠间隔轮询文件系统位置。如果没有任何变化,这种方法会浪费CPU资源。

3.2. 回调方法

WatchService API不提供回调方法,而是提供了两种类型的轮询方法来检查是否有新的更改事件可供处理:

  1. 块操作方法,如poll()(带有超时参数)和take()
  2. 非阻塞方法,如poll()(无超时参数)。

使用块操作方法,当有新的更改事件可用时,应用程序线程才会开始处理。因此,它不需要不断轮询获取新事件。

这些方法的详细信息和用法可以在我们的文章这里找到。

相反,Apache Commons IO库在FileAlterationListener接口上提供了回调方法,当检测到文件系统位置或目录的变化时会被调用。

FileAlterationObserver observer = new FileAlterationObserver("pathToDir");
FileAlterationMonitor monitor = new FileAlterationMonitor(POLL_INTERVAL);
FileAlterationListener listener = new FileAlterationListenerAdaptor() {
    @Override
    public void onFileCreate(File file) {
        // code for processing creation event
    }

    @Override
    public void onFileDelete(File file) {
        // code for processing deletion event
    }

    @Override
    public void onFileChange(File file) {
        // code for processing change event
    }
};
observer.addListener(listener);
monitor.addObserver(observer);
monitor.start();

3.3. 事件溢出

WatchService API由操作系统事件驱动,因此如果应用程序无法快速处理事件,有可能发生操作系统事件缓冲区溢出的情况。在这种情况下,会触发OVERFLOW事件,表示一些事件在应用程序读取它们之前已丢失或被丢弃。

这需要在应用程序中妥善处理OVERFLOW事件,以确保能够处理可能引发OVERFLOW事件的突然大量更改事件。

另一方面,Apache Commons IO库不基于操作系统事件,因此没有溢出的问题。

每次轮询时,观察者都会获取目录中的文件列表,并与上一次轮询获得的列表进行比较。

  1. 如果在上次轮询中发现新文件名,会调用监听器上的onFileCreate()方法。
  2. 如果在上一次轮询中找到的文件名在最后一次轮询中获取的文件列表中缺失,会调用监听器上的onFileDelete()方法。
  3. 如果找到匹配项,会检查文件的属性,如最后修改日期、长度等是否有变化。如果有变化,会调用监听器上的onFileChange()方法。

4. 总结

在这篇文章中,我们成功突出了两个API的关键差异。

一如既往,本文示例的完整源代码可在我们的GitHub项目这里找到。