当前位置: 首页 > 知识库问答 >
问题:

ForkJoinPool与普通递归

闻人和歌
2023-03-14

在阅读了关于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);
    }
}
    null

共有1个答案

晋安国
2023-03-14

生活中没有什么是免费的。如果你必须把一个啤酒板条箱从你的车搬到你的公寓--什么更快:手动把它搬到那里,还是先去小屋,让独轮车用它来搬那一个板条箱?

创建线程对象是一个“本机”操作,它进入底层操作系统以获取那里的资源。这可能是一个相当昂贵的行动。

意思是:仅仅在一个问题上抛出“更多的线程”并不能自动加快速度。恰恰相反。当您的任务主要是CPU密集型的时候,并行处理可能会有很小的收益。当您正在执行大量IO时,那么拥有多个线程可以让您在总体上“少”等待;从而提高吞吐量。

为了进一步阅读,您可以查看并行流。它们使用Fork/Join框架;令人惊讶的是,期望任意ParallelStream也比普通流“快”是一个错误的概念。

 类似资料:
  • 问题内容: 如果下面的代码会产生相同的结果,为什么还要使用封装? 封装的主要好处是能够修改我们已实现的代码而不会破坏其他使用我们代码的人的代码。 但是我可以在不使用封装的情况下使用此好处,对吗?因为每个对象的字段都彼此不同。 问题答案: 您的问题很有趣。我将尽力为您解答。 封装 背后的主要思想 是向 其他用户 隐藏数据及其实现 细节。如果我们将数据成员设为 私有 ,则只能在同一类中访问它。没有其他

  • 问题内容: 我正在尝试在旧版Java / Spring / Hibernate项目中执行cron作业,因此我决定使用spring调度程序。 我希望myTask.doStuff在每个月的第一个星期日的12:00运行。 在我的application-context.xml中,我已将任务调度程序配置为: 问题cron表达式本身是: 0 0 12? 1/1 SUN#1 * 并且是一个bean,它有一个名为

  • 我对和的内部调度机制有点困惑。 同时,显示为不同的,因为它使用了工作窃取算法。如果我理解正确,它意味着一个线程可以从另一个线程窃取一些任务。 然而,我并不真正理解和中实现的机制之间的区别。从我的理解来看,两种机制都应该尽可能减少每个线程的空闲时间。 如果在的情况下,每个线程都有自己的队列,我会理解的。然而,情况并非如此,因为队列是由池的不同线程共享的。

  • 参考Java的Fork/Join vs ExecutorService-何时使用哪个?,传统的线程池通常用于处理许多独立请求;用于处理连贯/递归任务,其中一个任务可能会产生另一个子任务并稍后加入。 那么,为什么Java-8的默认使用而不是传统的执行器? 在许多情况下,我们在或之后使用,然后提交一个函数式接口作为参数。从我的角度来看,这些任务是独立的,不是吗?

  • 问题内容: 我应该使用php PDO还是普通的mysql_connect在PHP中执行数据库查询? 哪一个更快? PDO的一大优点是接口在多个数据库之间是一致的。对于准备好的语句,也有一些很酷的功能,这些功能避免了转义所有查询字符串的麻烦。PDO的可移植性大于mysql_connect。 那么,出于这些原因,我应该使用PDO还是坚持使用传统的mysql_connect? 问题答案: PDO比mys

  • 我想通过以下方法将<code>Runnable<code>任务提交到ForkJoinPool: 注意,我使用JDK 7。 在引擎盖下,它们被转换为ForkJoinTask对象。我知道ForkJoinPool在任务递归地分成较小的任务时是有效的。 问题: 如果没有递归,工作窃取在ForkJoinPool中仍然有效吗? 在这种情况下值得吗? 更新1:任务小,可以不平衡。即使对于严格相等的任务,如上下文