我需要对一个文件夹内的所有文件进行只读处理,且需要递归操作。我正在使用 Files.walk
获取文件流,但我注意到该API指定walk
仅返回常规流而不是并行流。
如何才能并行处理目录中的所有文件?
我需要对一个文件夹内的所有文件进行只读处理,且需要递归操作。我正在使用 Files.walk
获取文件流,但我注意到该API指定walk
仅返回常规流而不是并行流。
如何才能并行处理目录中的所有文件?
您可以通过调用Stream::parallel
将任何Stream
转换为并行Stream
。
Stream<Path> stream = Files.walk(startPath).parallel().forEach(...);
Files.walk
的并行化能力较差,特别是在子树下的文件数量少于1024个时。如果您需要对每个文件进行大量处理且文件数不多,使用Files.walk(path).collect(toList()).parallelStream()
可能会更加高效。 - Tagir ValeevSpliterators.spliteratorUnknownSize
,其分割策略是将块加载到包含1024个元素的数组中。由于大小未知,流水线引擎假定分割产生的部分相等,但实际上并非如此(对于<=1024输入的第一次分割,所有元素都倒入前缀中,使后缀中没有任何元素)。这导致非常糟糕的并行性能。 - Tagir Valeev我有同样的问题。调用 parallel()
将流转换为并行流后,Files.walk 流似乎不起作用。但实际上处理仍然只在一个线程中执行。
唯一的解决方案是将收集到的 Paths
转换成一个列表,并按照 Tagir Valeev 的建议创建一个并行流。
不可行的解决方案:
Files.walk(Paths.get(System.getProperty("user.dir")))
.parallel()
.filter(Files::isRegularFile)
...
解决方案:
Files.walk(Paths.get(System.getProperty("user.dir")))
.collect(Collectors.toList())
.parallelStream()
.filter(Files::isRegularFile)
...
Files.walk(...).parallel()
可能是一个选择。 - Flown