首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >WatchService大量目录(递归)

WatchService大量目录(递归)
EN

Stack Overflow用户
提问于 2022-05-14 15:21:40
回答 1查看 105关注 0票数 0

我想检测目录中的变化,所以我使用WatchService实现

代码语言:javascript
复制
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
}

这是主要的方法

代码语言:javascript
复制
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有用吗?如果是,你能提供伪码吗?如果没有,是否有优化的解决方案?谢谢

EN

回答 1

Stack Overflow用户

发布于 2022-05-14 19:36:02

每个文件系统只需要一个新的WatchService,而不是每个目录,并且只需要一个轮询循环/线程来处理每个WatchService

现在,您已经设置了每个文件夹的WatchService和轮询循环,这将很难对5万个文件夹进行缩放(没有挂起虚拟线程)。固定大小的线程池是不合适的。

相反,要跟踪FilesystemWatchService的映射,并将新文件夹注册到相应的文件系统的单个WatchService

为每个新的WatchService启动一个新的服务/轮询线程,它将处理从同一个文件系统注册的多少文件夹。

对于许多应用程序来说,WatchService+轮询线程的单个配对可以处理同一个文件系统的所有文件夹。来自每个WatchService的轮询事件将用于对许多文件夹的更改,并且事件会告诉您哪个文件夹。

为了简单起见,您可能会考虑使用额外的WatchService+线程对来处理特定的子树--但每个文件夹的WatchService+thread永远不会超过1,00个线程。

请注意,无论您决定设置多少WatchService和线程,事件轮询循环都非常冗长,因此您应该始终整理要稍后执行的操作。将其视为JavaFx/Swing/AWT事件处理程序-记录要处理的任务,以便在轮询循环之外执行操作。请参阅这个collating watch events示例。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72241588

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档