为了账号安全,请及时绑定邮箱和手机立即绑定

ForkJoinPool - 为什么程序抛出 OutOfMemoryError?

ForkJoinPool - 为什么程序抛出 OutOfMemoryError?

largeQ 2021-06-22 01:11:49
我想在 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。我的理解是最大线程数(包括补偿线程)是有界的,那么为什么会出现这个错误呢?我的程序中是否缺少任何内容?
查看完整描述

1 回答

?
鸿蒙传说

TA贡献1865条经验 获得超7个赞

只需要一个小的改变。您需要为 newWorkStealingPool 指定并行度,如下所示:

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

根据其文档:

newWorkStealingPool(int parallelism) -> 创建一个线程池,维护足够的线程以支持给定的并行度级别,并且可以使用多个队列来减少争用。并行度级别对应于主动参与或可用于参与任务处理的最大线程数。线程的实际数量可能会动态增长和收缩。工作窃取池不保证提交任务的执行顺序。

根据随附的 Java Visual VM 屏幕截图,这种并行性允许程序在指定的内存中工作并且永远不会耗尽内存。

//img1.sycdn.imooc.com//60d3098f00015fd506110485.jpg

而且,还有一件事(不确定它是否会产生任何影响):


更改调用 fork 的顺序并将任务添加到列表中。也就是说,改变


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

recursiveTasks.add(task);

task.fork();


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

task.fork();

recursiveTasks.add(task);


查看完整回答
反对 回复 2021-06-23
  • 1 回答
  • 0 关注
  • 485 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信