2018-06-09总结:

ForkJoin确实可以很快速的去解析文件并统计关键词的数量,但是如果文件过大就会出现内存溢出,是否可以通过虚拟内存方式解决内存溢出的问题呢?

package com.oxygen.forkjoin.model;

import java.util.List;
/**
 * 文档
 * @author renguanyu
 *
 */
public class Document {

    private List<String> lines;

    public Document(List<String> lines) {
        super();
        this.lines = lines;
    }

    public List<String> getLines() {
        return lines;
    }

    public void setLines(List<String> lines) {
        this.lines = lines;
    }

}
package com.oxygen.forkjoin.model;

import java.util.List;
/**
 * 文件夹
 * @author renguanyu
 *
 */
public class Folder {

    private List<Folder> subFolders;
    private List<Document> documents;

    public Folder(List<Folder> subFolders, List<Document> documents) {
        this.subFolders = subFolders;
        this.documents = documents;
    }

    public List<Folder> getSubFolders() {
        return subFolders;
    }

    public void setSubFolders(List<Folder> subFolders) {
        this.subFolders = subFolders;
    }

    public List<Document> getDocuments() {
        return documents;
    }

    public void setDocuments(List<Document> documents) {
        this.documents = documents;
    }

}
package com.oxygen.forkjoin.service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import com.oxygen.forkjoin.model.Document;
/**
 * 文档服务
 * @author renguanyu
 *
 */
public class DocumentService {

    /**
     * 读取文件中所以数据
     * @param file 文件
     * @return 文档
     */
    public static Document fromFile(File file) {
        List<String> lines = new ArrayList<>();
        try(BufferedReader reader = new BufferedReader(new FileReader(file))) {
            String line = reader.readLine();
            while (line != null) {
                lines.add(line);
                line = reader.readLine();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return new Document(lines);
    }

}
package com.oxygen.forkjoin.service;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ForkJoinPool;

import com.oxygen.forkjoin.model.Document;
import com.oxygen.forkjoin.model.Folder;
import com.oxygen.forkjoin.task.FolderSearchTask;
/**
 * 文件夹服务
 * @author renguanyu
 *
 */
public class FolderService{

    /**
     * 递归查询文件夹中所有的数据
     * 1.在内存中建立文件夹的结构
     * 2.把数据都加载到这个结构中,方便下一步计算
     * @param dir 文件夹
     * @return 文件夹
     */
    public static Folder fromDirectory(File dir) {
        List<Document> documents = new ArrayList<>();
        List<Folder> subFolders = new ArrayList<>();
        for (File entry : dir.listFiles()) {
            if (entry.isDirectory()) {
                subFolders.add(FolderService.fromDirectory(entry));
            } else {
                documents.add(DocumentService.fromFile(entry));
            }
        }
        return new Folder(subFolders, documents);
    }

    /**
     * 获取关键词总数
     * @param targetFolder 目标文件夹
     * @param keyword 关键词
     * @throws IOException
     */
    public static long getKeywordTotal(String targetFolder, String keyword) {
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        //把文件夹中的数据加载到内存中,我这个文件夹中就一个日志文件
        File dir = new File(targetFolder);
        Folder folder = FolderService.fromDirectory(dir);
        //创建一个搜索任务
        FolderSearchTask task = new FolderSearchTask(folder, keyword);
        //开始执行fork/join任务
        long counts = forkJoinPool.invoke(task);
        return counts;
    }

}
package com.oxygen.forkjoin.task;
import java.util.List;
import java.util.concurrent.RecursiveTask;

import com.oxygen.forkjoin.model.Document;
/**
 * 文档搜索任务
 * @author renguanyu
 *
 */
public class DocumentSearchTask extends RecursiveTask<Long> {

    private static final long serialVersionUID = 1L;

    private Document document;
    private String searchedWord;

    public DocumentSearchTask(Document document, String searchedWord) {
        super();
        this.document = document;
        this.searchedWord = searchedWord;
    }

    @Override
    protected Long compute() {
        long count = 0;
        List<String> lines = document.getLines();
        for (String line : lines) {
            String[] words = line.trim().split("(\\s|\\p{Punct})+");
            for (String word : words) {
                if (searchedWord.equals(word)) {
                    count = count + 1;
                }
            }
        }
        return count;
    }

}
package com.oxygen.forkjoin.task;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.RecursiveTask;

import com.oxygen.forkjoin.model.Document;
import com.oxygen.forkjoin.model.Folder;
/**
 * 文件夹搜索任务
 * @author renguanyu
 *
 */
public class FolderSearchTask extends RecursiveTask<Long> {

    private static final long serialVersionUID = 1L;

    private Folder folder;
    private String searchedWord;

    public FolderSearchTask(Folder folder, String searchedWord) {
        super();
        this.folder = folder;
        this.searchedWord = searchedWord;
    }
    //计算方法
    @Override
    protected Long compute() {
        long count = 0L;
        List<RecursiveTask<Long>> forks = new ArrayList<>();
        //获取文件夹下的子文件夹
        for (Folder subFolder : folder.getSubFolders()) {
            //递归文件夹搜索任务
            FolderSearchTask task = new FolderSearchTask(subFolder, searchedWord);
            //把任务添加到分叉列表,用于合并任务
            forks.add(task);
            //放到工作队列中
            task.fork();
        }
        //获取文件夹下的文档
        for (Document document : folder.getDocuments()) {

            DocumentSearchTask task = new DocumentSearchTask(document, searchedWord);
            //把任务添加到分叉列表,用于合并任务
            forks.add(task);
            //放到工作队列中
            task.fork();
        }
        //合并工作队列中各个线程计算结果的值
        for (RecursiveTask<Long> task : forks) {
            count = count + task.join();
        }
        return count;
    }
}
package com.oxygen.forkjoin.test;

import java.io.IOException;
import com.oxygen.forkjoin.service.FolderService;
/**
 * 测试程序
 * @author renguanyu
 *
 */
public class MainTest {

    public static void main(String[] args) throws IOException {

        long startTime = System.currentTimeMillis();

        long counts = FolderService.getKeywordTotal("C:\\test\\logs\\", "null");

        long stopTime = System.currentTimeMillis();

        long completeTime = stopTime - startTime;

        System.out.println(counts + " , fork / join search took " + completeTime + "ms");
    }
}

ForkJoin统计文件夹中包含关键词的数量的更多相关文章

  1. Path,Files巩固,题目:从键盘接收两个文件夹路径,把其中一个文件夹中(包含内容)拷贝到另一个文件夹中

    这个题目用传统的File,InputStream可以做,但是如果用Files,Path类做,虽然思路上会困难一些,但是代码简洁了很多,以下是代码: import java.io.IOException ...

  2. 使用.NET统计文件夹中文件总数

    软件下载: http://hovertree.com/h/bjaf/hwqtjwjs.htm 截图: 使用方法:点击按钮,选择文件夹,就可以显示文件夹中包含的文件总数. 这个项目包含在HoverTre ...

  3. 【linux】统计文件夹中文件行数

    统计当前目录下,排除venv目录,剩余所有py文件的行数 wc -l `find -path ./venv -prune -o -name '*py'`

  4. java基础 File 递归删除文件夹中所有文件文件夹 目录(包含子目录)下的.java文件复制到e:/abc文件夹中, 并统计java文件的个数

    File 递归删除文件夹中所有文件文件夹 package com.swift.kuozhan; import java.io.File; import java.util.Scanner; /*键盘录 ...

  5. 用字符流实现每个文件夹中创建包含所有文件信息的readme.txt

    package com.readme; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; i ...

  6. 用C语言实现统计一个文件夹中各种文件的比例

    <UNIX环境高级编程>中的程序清单4-7就介绍了如何实现递归地统计某个目录下面的文件!我刚开始看过它的代码后,觉得照着敲太没意思了,所以就合上书自己写了一遍!为此还写了一篇博文,这是博文 ...

  7. (文档)Shader.Find (在编译时,只包含那些使用中的shader或位置在"Resources"文件夹中shader)

    Shader.Find 查找 static function Find (name : string) : Shader Description描述 Finds a shader with the g ...

  8. 【原】Mac下统计任意文件夹中代码行数的工

    [链接][原]Mac下统计任意文件夹中代码行数的工http://www.cnblogs.com/wengzilin/p/4580646.html

  9. .net网站上传图片换电脑不显示 当不用网站的IP地址访问图片,只用相对路径访问时,在发布网站的时候,将上传图片的目标文件夹,包含在项目中再发布即可。

    .net网站上传图片换电脑不显示 当不用网站的IP地址访问图片,只用相对路径访问时,在发布网站的时候,将上传图片的目标文件夹,包含在项目中再发布即可.

随机推荐

  1. P1075 语句解析

    题目描述 一串长度不超过 255 的 PASCAL 语言代码,只有 a,b,c 3 个变量,而且只有赋值语句,赋值只能是一个一位的数字或一个变量,每条赋值语句的格式是 [变量]:=[变量或一位整数]; ...

  2. java 一个类加载器的高级问题分析

    编写一个能打印出自己的类加载器名称和当前类加载器的父子结构关系链的MyServlet,正常发布后,看到打印结果为WebAppClassloader. 把MyServlet.class文件打jar包,放 ...

  3. slot的使用方法

    参考链接:https://www.cnblogs.com/loveyt/p/9946450.html 插槽的使用其实是很简单,你只需明白以下两点,就很容易理解. 1.插槽是使用在子组件中的, 2.插槽 ...

  4. 37.html

    转载:https://www.cnblogs.com/yuanchenqi/articles/5976755.html 前端概述 import socket def main(): sock = so ...

  5. IDEA环境使用Git

    推送到Github 在设置中登录github账户 点击OK 将项目交给Git管理 之后项目文件就会变成红色 添加文件到暂存区 点击Add之后,项目文件会变成绿色 添加文件到本地仓库 点击Commit ...

  6. mysql主从之多元复制

    实验环境: 192.168.132.121   master1 192.168.132.122   master2 192.168.132.123   slave 使用gtid的方式 两个主分别是19 ...

  7. 天猫SSM项目学习记录(一)----第一个相对完整的SSM项目

    来源:  http://how2j.cn/k/tmall_ssm/tmall_ssm-1516/1516.html?p=78908 目的:记录一个相对完整的SSM项目模板 1.工具:idea2018商 ...

  8. javascript数组大全(一张图列出数组的所有方法)

    把所有数组的方法列在了一张图上,为了自己温故一下,也为了以后忘记时好查阅. 如果大家在上面查阅方法,可以找到对应的方法名,看前面简单的注释,还是不能明白的话,可以看一下官网说明,地址给大家列出来,MD ...

  9. Python第二天了哇

    在Python中input是接收用户输入的一个函数哇 a = int( b) 这个的意思是把b的值转换为整型? 好像是这个亚子 Python想要知道它的内置函数的话可以在Python的交互界面(She ...

  10. MicroPython TPYBoard v702实现HTTP应用功能

    [Micropython]TPYBoard v702 HTTP应用功能 转载请注明文章来源,更多教程可自助参考docs.tpyboard.com,QQ技术交流群:157816561,公众号:Micro ...