[英]WatchService large number of directory (recursive)
我想检测目录内的变化,所以我使用 WatchService 来实现
public class DirWatcher implements Runnable {
private Path path;
private ExecutorService exe;
public DirWatcher(Path path, ExecutorService exe) {
this.path = path;
this.exe = exe;
}
public void start() throws Exception {
WatchService watchService = FileSystems.getDefault().newWatchService();
path.register(watchService, StandardWatchEventKinds.ENTRY_CREATE, StandardWatchEventKinds.ENTRY_DELETE, StandardWatchEventKinds.ENTRY_MODIFY);
WatchKey key;
while ((key = watchService.take()) != null) {
for (WatchEvent<?> event : key.pollEvents()) {
if(isFileEvent(event)) {
// do stuff with file
} else if(isNewDirCreated(event)) {
Path dir = getPath(event, path);
DirWatcher newWatcher = new DirWatcher(dir, exe);
exe.execute(newWatcher);
}
}
key.reset();
}
watchService.close();
}
public void run() {
try {
start();
} catch(Exception e) {
}
}
//Other methods
}
这是主要方法
public class DirectoryWatcherExample {
public static void main(String[] args) throws Exception {
Path root = getRootPath();
ExecutorService exe = Executors.newFixedThreadPool(//HOW BIG THE POOL SHOULD I INIT? THE NUMBER OF DIRECTORIES IS LARGE (> 50000))
DirWatcher watcher = new DirWatcher(root, exe);
exe.execute(watcher);
List<Path> paths = listRecrursive(root);
paths.stream().map(p -> new DirWatcher(p, exe)).forEach(exe::execute);
}
}
我的问题是:我应该如何初始化线程池? 由于任务数量巨大(> 50000)。 它会影响服务器(64 Gb RAM)吗?
ForkJoinPool 和 RecursiveTask 在这种情况下有用吗? 如果是,你能提供伪代码吗? 如果没有,是否有任何优化的解决方案? 谢谢
每个文件系统只需要一个新的WatchService
,而不是每个目录,并且只需要一个轮询循环/线程来处理每个WatchService
。
正如您现在所拥有的那样,您已经为每个文件夹设置了WatchService
和轮询循环,这对于 50,000 个文件夹(没有 LOOM 虚拟线程)很难扩展。 固定大小的线程池是不合适的。
而是跟踪Filesystem
到WatchService
的映射并将新文件夹注册到其相应文件系统的单个WatchService
。
为每个新的WatchService
启动一个新的服务/轮询线程,该线程将处理您从同一文件系统注册的多个文件夹。
对于许多应用程序,一对WatchService
+ 轮询线程可以处理同一文件系统的所有文件夹。 每个WatchService
的轮询事件将用于更改许多文件夹 - 并且这些事件会告诉您哪个文件夹。
为简单起见,您可能会考虑将额外的WatchService
+线程对专用于特定的子树 - 但每个文件夹绝不会有一个 WatchService + 线程,因为这意味着 1,000 个线程。
请注意,无论您决定设置多少WatchService
和线程,事件轮询循环都非常冗长,因此您应该始终整理操作以供稍后执行。 将其视为 JavaFx/Swing/AWT UI 事件处理程序 - 记录要处理的任务,以便在轮询循环之外执行操作。 请参阅这个整理监视事件的示例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.