猿问

ForkJoinPool - 为什么程序抛出 OutOfMemoryError?

我想在 Java 8 中尝试 ForkJoinPool,所以我编写了一个小程序来搜索给定目录中名称包含特定关键字的所有文件。


程序:


public class DirectoryService {


    public static void main(String[] args) {

        FileSearchRecursiveTask task = new FileSearchRecursiveTask("./DIR");

        ForkJoinPool pool = (ForkJoinPool) Executors.newWorkStealingPool();

        List<String> files = pool.invoke(task);

        pool.shutdown();

        System.out.println("Total  no of files with hello" + files.size());

    }


}


    class FileSearchRecursiveTask extends RecursiveTask<List<String>> {

        private String path;

        public FileSearchRecursiveTask(String path) {

            this.path = path;

        }


        @Override

        protected List<String> compute() {

            File mainDirectory = new File(path);

            List<String> filetedFileList = new ArrayList<>();

            List<FileSearchRecursiveTask> recursiveTasks = new ArrayList<>();

            if(mainDirectory.isDirectory()) {

                System.out.println(Thread.currentThread() + " - Directory is " + mainDirectory.getName());

                if(mainDirectory.canRead()) {

                    File[] fileList = mainDirectory.listFiles();

                    for(File file : fileList) {

                        System.out.println(Thread.currentThread() + "Looking into:" + file.getAbsolutePath());

                        if(file.isDirectory()) {

                            FileSearchRecursiveTask task = new FileSearchRecursiveTask(file.getAbsolutePath());

                            recursiveTasks.add(task);

                            task.fork();

                        } else {

                            if (file.getName().contains("hello")) {

                                System.out.println(file.getName());

                                filetedFileList.add(file.getName());

                            }

                        }

                    }

                }

当目录没有太多子目录和文件时,这个程序工作正常,但如果它真的很大,那么它会抛出 OutOfMemoryError。


我的理解是最大线程数(包括补偿线程)是有界的,那么为什么会出现这个错误呢?我的程序中是否缺少任何内容?


largeQ
浏览 486回答 1
1回答

鸿蒙传说

只需要一个小的改变。您需要为 newWorkStealingPool 指定并行度,如下所示:ForkJoinPool&nbsp;pool&nbsp;=&nbsp;(ForkJoinPool)&nbsp;Executors.newWorkStealingPool(5);根据其文档:newWorkStealingPool(int parallelism) -> 创建一个线程池,维护足够的线程以支持给定的并行度级别,并且可以使用多个队列来减少争用。并行度级别对应于主动参与或可用于参与任务处理的最大线程数。线程的实际数量可能会动态增长和收缩。工作窃取池不保证提交任务的执行顺序。根据随附的 Java Visual VM 屏幕截图,这种并行性允许程序在指定的内存中工作并且永远不会耗尽内存。而且,还有一件事(不确定它是否会产生任何影响):更改调用 fork 的顺序并将任务添加到列表中。也就是说,改变FileSearchRecursiveTask task = new FileSearchRecursiveTask(file.getAbsolutePath());recursiveTasks.add(task);task.fork();至FileSearchRecursiveTask task = new FileSearchRecursiveTask(file.getAbsolutePath());task.fork();recursiveTasks.add(task);
随时随地看视频慕课网APP

相关分类

Java
我要回答