使用Fork/Join实现WordCount例子

Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。
Fork/Join框架是一个比较特殊的线程池框架,专用于需要将一个任务不断分解成子任务(分叉),再不断进行汇总得到最终结果(结合)的计算过程。
比起传统的线程池类ThreadPoolExecutor,ForkJoinPool 实现了工作窃取算法,使得空闲线程能够主动分担从别的线程分解出来的子任务,
从而让所有的线程都尽可能处于饱满的工作状态,提高执行效率。

下面将演示一个使用Fork/Join实现WordCount例子,假设有一个目录,里面都是文本文件,现在要统计这些所有的文件里面的字符串的个数

package com.fork;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.RecursiveTask;

/**
 * RecursiveTask 表示有返回值的计算
 */
public class FileRecursiveTask extends RecursiveTask> {

	private static final long serialVersionUID = 1L;
	private final List contents;
	
	public FileRecursiveTask(File file) {
		System.out.println("处理文件:" + file.getAbsolutePath());
		try {
			contents = Files.readAllLines(Paths.get(file.toURI()));
		} catch (IOException e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 业务逻辑处理,相当于map
	 */
	protected Map compute() {
		Map map = new HashMap<>();
		for(String content : contents){
			String[] strs = content.split(" ");
			for(String str : strs){
				if(map.containsKey(str)){
					int val = map.get(str);
					map.put(str, val+1);
				} else {
					map.put(str, 1);
				}
			}
		}
		return map;
	}
}
package com.fork;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

/**
 * 每个文件会使用一个线程去处理,最终汇总到一起
 */
public class ForkRecursiveTask extends RecursiveTask> {

	private static final long serialVersionUID = 1L;
	private final File[] files;
	
	public ForkRecursiveTask(String path) {
		files = new File(path).listFiles();
	}
	
	/**
	 * 汇总处理,相当于reduce
	 */
	protected Map compute() {
		List>> tasks = new ArrayList<>();
		for(File file : files){
			FileRecursiveTask frt = new FileRecursiveTask(file);
			tasks.add(frt.fork());
		}
		
		Map result = new HashMap<>();
		for(ForkJoinTask> task : tasks){
			Map map = task.join();
			for(String key : map.keySet()){
				if(result.containsKey(key)){
					result.put(key, result.get(key) + map.get(key));
				} else {
					result.put(key, map.get(key));
				}
			}
		}
		return result;
	}
}
package com.fork;

import java.util.Map;
import java.util.concurrent.ForkJoinPool;

public class ForkJoinPoolTest {
	public static void main(String[] args) {
		ForkJoinPool forkJoinPool = new ForkJoinPool();
		Map map = forkJoinPool.invoke(new ForkRecursiveTask("e:/txts"));
		//输出最终所有的计算结果
		for(String key : map.keySet()){
			System.out.println(key + "=" + map.get(key));
		}
	}
}







你可能感兴趣的:(Java)