有没有办法使用 WatchService 强制轮询?

2022-09-03 08:10:08

我有工作代码,可以使用WatchService侦听目录并响应我指定的事件。这工作正常,并且已经在linux和Mac上进行了测试(尽管在后者上很明显使用了轮询)。

但是,当我在生产中部署它时,事实证明被监视的目录是NFS挂载。由于WatchService在Linux上运行时使用inotify,因此从未触发任何事件,因为NFS挂载不会触发inotify事件(或类似的东西,这里有更多信息,这解释了我的问题:Java WatchService在观看映射驱动器时不生成事件)。

由于我的代码已经编写完毕,因此我更愿意强制 WatchService 使用轮询实现,而不是 inotify 实现。有没有办法做到这一点?

我通过查找 sun.nio.fs.PollingWatchService 源代码并直接创建一个对象(而不是使用 FileSystems.getDefault().newWatchService())来尝试此操作,但是当使用 Path 注册服务时,我得到了这个例外:java.nio.file.ProviderMismatchException。

那么,有什么想法吗?由于我已经使用WatchService和WatchKey API实现了代码,因此强制轮询比使用自定义或第三方轮询器重写所有内容要容易得多。谢谢!


答案 1

你可以试试开源项目jpoller。它实现了一个名为 DirectoryPoller 的类,该类定期轮询一个或多个目录的内容。它是一个周期性线程,使用文件上次修改时间查找新文件。要下载源代码,您可以访问 http://jpoller.sourceforge.net/ 老实说,我没有使用jpoller。我使用了 JDK 7 WatcherService 事件。


答案 2

我们遇到了类似的问题,并决定放弃使用WatchService。有几个库实现了池化。我会推荐Apache Commons IO Monitor:

https://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/monitor/package-summary.html


推荐