2015-11-08 2 views
6

Мне нужно сделать некоторую обработку только для чтения на всех файлах в папке рекурсивно. Я использую Files.walk, чтобы получить поток файлов, но я заметил, что api указывает, что walk возвращает только обычный поток, а не параллельный поток.Как я могу получить параллельный поток Files.walk?

Как я могу обрабатывать все файлы в каталоге параллельно?

+4

Возможно, что-то вроде 'Files.walk (...). Parallel()'? – Flown

+0

@Flown Hah ... глупо меня. Не понял, что вы можете конвертировать обычные потоки в параллельные. –

ответ

15

Вы можете преобразовать любые Stream в параллель Stream, вызвав Stream::parallel.

Stream<Path> stream = Files.walk(startPath).parallel().forEach(...); 
+9

Обратите внимание, что 'Files.walk' распараллеливается плохо, особенно если ваше поддерево имеет менее 1024 файлов. Если у вас много обработки файлов и не так много файлов, было бы, вероятно, более эффективно «Files.walk (путь) .collect (toList()). ParallelStream()'. –

+1

@TagirValeev Интересно. У вас есть ссылка, объясняющая, почему это так? –

+7

@DavidGrinberg, исходный код JDK и эталонные тесты. Он использует внутри себя 'Spliterators.spliteratorUnknownSize', стратегия разделения которого заключается в загрузке кусков в массивы, начиная с 1024 элементов. По мере того, как размер неизвестен, движок потокового потока предполагает, что split производит четные части, но на самом деле они не являются (сначала разделение на <= 1024 входных дампов всех элементов в префикс, не оставляя никаких элементов для суффикса). Это приводит к очень плохой параллельной работе. –

Смежные вопросы