阅读关于 ForkJoinPool 后,我尝试了一个实验来测试与普通递归相比,ForkJoinPool
的实际速度有多快。
我递归地计算了一个文件夹中的文件数量,令我惊讶的是,普通递归比 ForkJoinPool
这是我的代码。
递归任务
class DirectoryTask extends RecursiveTask<Long> {
private Directory directory;
@Override
protected Long compute() {
List<RecursiveTask<Long>> forks = new ArrayList<>();
List<Directory> directories = directory.getDirectories();
for (Directory directory : directories) {
DirectoryTask directoryTask = new DirectoryTask(directory);
forks.add(directoryTask);
directoryTask.fork();
}
Long count = directory.getDoumentCount();
for (RecursiveTask<Long> task : forks) {
count += task.join();
}
return count;
}
}
普通递归
private static Long getFileCount(Directory directory) {
Long recursiveCount = 0L;
List<Directory> directories = directory.getDirectories();
if (null != directories) {
for (Directory d : directories) {
recursiveCount += getFileCount(d);
}
}
return recursiveCount + directory.getDoumentCount();
}
目录对象
class Directory {
private List<Directory> directories;
private Long doumentCount = 0L;
static Directory fromFolder(File file) {
List<Directory> children = new ArrayList<>();
Long documentCount = 0L;
if (!file.isDirectory()) {
throw new IllegalArgumentException("Only directories are allowed");
}
String[] files = file.list();
if (null != files) {
for (String path : files) {
File f = new File(file.getPath() + File.separator + path);
if (f.isHidden()) {
continue;
}
if (f.isDirectory()) {
children.add(Directory.fromFolder(f));
} else {
documentCount++;
}
}
}
return new Directory(children, documentCount);
}
}
结果
- 普通递归:3 毫秒
- ForkJoinPool:25 毫秒
哪里错了?
我只是想了解是否存在特定阈值,低于该阈值时,普通递归比 ForkJoinPool 更快。
最佳答案
生活中没有免费的东西。如果您必须将一个啤酒箱从您的汽车移动到您的公寓 - 哪个更快:手动将其运送到那里,或者先去棚屋,让手推车用它来移动那个箱子?
创建线程对象是一种“ native ”操作,它会进入底层操作系统以获取那里的资源。这可能是一个相当昂贵的操作。
意思是:仅仅在一个问题上投入“更多线程”并不会自动加快速度。与此相反的。当您的任务主要是 CPU 密集型任务时,并行执行任务可能会带来很小的 yield 。当您进行大量 IO 时,拥有多个线程可以让您总体上“减少”等待;从而提高您的吞吐量。
换句话说:Fork/Join 需要相当多的 Activity 才能完成真正的工作。将它用于只需要几毫秒的计算简直是矫枉过正。因此:您会寻找适用于更大数据集的“fork/join”操作。
要进一步阅读,您可以查看 parallel streams .那些在幕后使用 fork/join 框架;令人惊讶的是,期望任意 parallelStream
也比普通流“更快”是一种误解。
关于java - ForkJoinPool 与普通递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43433874/