有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

如何在Java中以非阻塞方式列出目录中的文件?

在Java中,使用nio包中的Files在目录中列出“文件”很简单:

Stream<Path> paths = Files.list(Path.of("<folder>"))

但是,对Files.list(..)的调用被阻塞。如何以非阻塞方式列出目录中的文件

更新

所谓“阻塞”,我的意思是在反应式编程的上下文中不阻塞任何线程。在我的例子中,我使用来自Springproject reactor,我有一个定义如下的方法:

public Flux<String> doStuffWithFilesInDirectory(String dir) {
    // Intellij complains that the call to "Files.list(..)" is inappropriate since it's a blocking call
    var fileStream = Files.list(Path.of(dir)); 
    return Flux.fromStream(fileStream). ..
}

共 (2) 个答案

  1. # 1 楼答案

    磁盘的本质是不能立即产生信息。因此,可能的“非阻塞”解决方案是

    (a)在单独线程中同步阻塞执行,或

    (b)使用某种通知机制(回调、未来等)启动异步操作,以告知何时完成

    在后一种情况下,不仅需要通过某种Java方法实现这一点,还需要底层操作系统提供支持。由于并非所有系统都提供“异步readdir”,我怀疑您也找不到Java接口。这是一个基于一般推理的论点,所以我可能是错的——但我不会打赌

  2. # 2 楼答案

    如果您只想从调用线程异步运行Files.list,那么无需寻找“替代”文件API即可

    最基本的例子是:

    Runnable lister = () -> {
        try {
            SomeReceivingClassOrInstance
                .someEventMethod(Files.list(Path.of("yourPath")));
        }
        catch (IOException ioe) {
            // TODO handle
            ioe.printStackTrace();
        }
    };
    

    然后你可以:

    • 实现一个方法,该方法在接收端获取aStream<Path>,并对其进行操作
    • 从您希望异步启动操作的地方,使用new Thread(lister).start();异步调用您的Runnable

    请注意,有很多可选的、更优雅的/更高级的示例,可以异步运行操作

    这只是一个例子,说明您不需要进一步查看NIOAPI(例如使用FileVisitor等)来异步化它

    注意

    深思熟虑:如果您真的希望一个集合根据清单逐步“发现”的内容惰性地填充,那么您最好在它自己的线程中启动一个FileVisitor,并为每个条目填充一个线程安全的集合