java - 观看大量目录的最佳方式?
问题描述
我用Java/JavaFX 编写了一个音乐播放器,它(除其他外)监视用户的音乐库文件夹是否有任何更改,并在文件系统发生更改时更新程序的库数据。
我使用SimpleFileVisitor和WatchService完成此操作。SimpleFileVisitor
递归遍历目标文件夹层次结构,并将每个文件夹注册到WatchService
. 完整代码如下。
在我的 Ubuntu 18.04 上,如果我尝试以这种方式注册多个文件夹,每个文件夹都有很多子文件夹,我最终会收到错误java.io.IOException: User limit of inotify watches reached
。
事实证明,Linux 内核限制了文件中可以执行的 inotify 监视的数量/proc/sys/fs/inotify/max_user_watches
。常见的默认值是 8192。此限制适用于用户运行的每个程序,还有其他流行的程序使用很多,例如 DropBox。
我的图书馆可能也想要很多。对于可能使用该程序的用户来说,1000 - 25000 个想要被观看的文件夹是一个合理的估计。我预计大多数用户将落在 2000 - 5000 范围内。
一个解决方案是通知用户错误并告诉他们增加max_user_watches
内核中的数量,这是可以做到的,但如果可以避免的话,我不喜欢把这个负担放在用户身上。
是否有另一种好方法可以在不重载 Linux 上的 inotify 编号的情况下通知 java 中文件夹层次结构的更改?
我的完整观察者代码可以在这里找到,从第 545 行开始:https ://github.com/JoshuaD84/HypnosMusicPlayer/blob/55da2819a3862d5c2a14797a9ce45e9171f7076e/src/net/joshuad/hypnos/Library.java#L545
您还可以在此处查看主要的 walker 代码:
private void watcherRegisterAll ( final Path start ) {
try {
Files.walkFileTree(
start,
EnumSet.of( FileVisitOption.FOLLOW_LINKS ),
Integer.MAX_VALUE,
new SimpleFileVisitor <Path>() {
@Override
public FileVisitResult preVisitDirectory ( Path dir, BasicFileAttributes attrs ) throws IOException {
WatchKey key = dir.register(
watcher,
StandardWatchEventKinds.ENTRY_CREATE,
StandardWatchEventKinds.ENTRY_DELETE,
StandardWatchEventKinds.ENTRY_MODIFY
);
keys.put( key, dir );
return FileVisitResult.CONTINUE;
}
}
);
} catch ( IOException e ) {
LOGGER.log( Level.INFO, "Unable to watch directory for changes: " + start.toString() );
}
}
解决方案
您的方法是正确的,并且inotify
是最有效的方法。如果您遇到此问题,您可以提示用户代表他们增加限制以提供更好的用户体验(您必须通过询问密码来执行权限提升)。
推荐阅读
- python - 解析(OpenDocument)版本 1.2 使其变得简单
- python - 基于另一列的列中的Python百分比计算
- sql-server - 来自数据库的 Flutter Uint8list 字符串呈现为图像
- python - 如何在生成器表达式 Python 中添加限制
- c++ - C++ std::copy 与 std::uninitialized_copy
- pandas - Pandas 1.0.1 - 如何使用包含切片器的列表使用 MultiIndex 索引 DataFrame
- sql - 查找SQL中列值变化的时间范围
- python-3.x - 在我的代码中为 if 语句添加条件?
- javascript - Java Script - 用条件替换文本
- group-by - 在 AWS QLDB / Partiql 中使用 GROUP BY