Как перечислить файлы в каталоге неблокирующим способом в Java? - PullRequest
0 голосов
/ 08 ноября 2019

Перечислить «файлы» в каталоге просто на Java, используя Файлы из пакета nio:

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

Однако вызов Files.list(..) блокируется. Как я могу перечислить файлы в каталоге неблокирующим образом?

Обновление

Под «блокировкой» я подразумеваю не блокировать любой поток как в контексте реактивного программирования. В моем случае я использую проектный реактор из Spring , и у меня есть метод, определенный следующим образом:

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 ]

2 голосов
/ 08 ноября 2019

По своей природе диски не дают информацию мгновенно. Поэтому возможными «неблокирующими» решениями являются

(a) выполнение синхронной блокировки в отдельном потоке или

(b) инициирование асинхронной операции с некоторым механизмом уведомления (callback, Futureи т.д.), чтобы сказать вам, когда это будет сделано.

В последнем случае не только нужно, чтобы это было возможно с помощью какого-либо метода Java, но и соответствующая ОС должна обеспечивать поддержку. Поскольку не все системы предоставляют «асинхронный readdir», я подозреваю, что вы также не найдете интерфейс Java. Это аргумент из общих рассуждений, так что возможно я ошибаюсь - но я бы не стал на это ставить.

2 голосов
/ 08 ноября 2019

Если вы просто хотите запустить Files.list асинхронно из вызывающего потока, вы можете сделать это без поиска «альтернативных» файловых API.

Самым базовым примером будет:

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

. Затем вы можете:

  • реализовать метод, принимающий a Stream<Path> на стороне получателя, идействуя на.
  • Вызовите Runnable асинхронно с new Thread(lister).start();, с которого вы хотите начать операцию асинхронно

Обратите внимание, что существует множество альтернативных и более элегантных примеров более высокого уровня, чтобывыполнять операции асинхронно.

Это просто пример, демонстрирующий, что не нужно действительно нужно смотреть дальше в API nio (например, с FileVisitor и т. Д.), Чтобы асинхронизировать это.

Примечание

Включено после размышления: если вместо этого вы действительно хотите, чтобы собрание лениво заполнялось на основе того, что список постепенно «обнаруживает», то вам, вероятно, было бы лучше начатьFileVisitor в своем собственном потоке и заполнении потокобезопасного сбора для каждой записи.

...