Forkjoin框架执行任务并返回结果

Fork/join框架提供了执行任务并返回结果的能力。这些类型的任务都是通过RecursiveTask类来实现的。RecursiveTask类继承了ForkJoinTask类,并且实现了由执行器框架提供的Future框架。

在任务中,必须使用JavaApi文档推荐的如下结构:

	if(problem size > size){
		tasks=Divide(task);
		execute(tasks);
		groupResults();
		return result;
	}else{
		resolve problem;
		return result;
	}

如果任务需要解决的问题大于预定义的大小,那么就要将这个问题拆分成多个子任务,并使用Fork/join框架执行这些任务。执行完成后,原始任务获取到由所有这些子任务产生的结果,合并这些结果,返回最终结果。当原始任务在线程池中执行结束后,将高效的获取到整个问题的最终结果。

上代码,实现2种任务,1 它将遍历文档中的每一航来查找这个词;2 一个行任务,它将在文档的一部分当中查找这个词、

package com.xingfu.wx_2;

import java.util.Random;

import com.xingfu.wx.Utils;

/**
 * 
 * @author W,x
 * @version 创建时间:2015年4月16日 上午9:29:23
 * 
 */
public class Document {
	private String words[] = { "the", "hello", "goodbye", "packt", "java", "thread", "pool",
			"random", "class", "main" };

	/**
	 * @param numLines
	 *            行数
	 * @param numWords
	 *            每一行词的个数
	 * @param word
	 *            准备查找的词
	 * @return 一个字符串矩阵 2015年4月16日-上午9:31:34
	 * 
	 */
	public String[][] generateDocument(int numLines, int numWords, String word) {
		int counter = 0;
		String doucument[][] = new String[numLines][numWords];
		Random random = new Random();
		// 为字符串矩阵天上字符串,通过随机数取得数组words的某一个字符串,然后存入到字符串矩阵document对应的位置上,同事计算生成的字符串举证中将要查找的词出现的次数
		// 这个值可以用来与后续程序运行查找任务时的统计的次数想比较,检查两个值是否相同
		for (int i = 0; i < numLines; i++) {
			for (int j = 0; j < numWords; j++) {
				int index = random.nextInt(words.length);
				doucument[i][j] = words[index];
				if (doucument[i][j].equals(word)) {
					counter++;
				}
			}
		}
		Utils.print("DocumentMock: the word appears " + counter + " times in the doucment");
		return doucument;

	}
}


 

package com.xingfu.wx_2;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RecursiveTask;

/**
 * 
 * @author W,x
 * @version 创建时间:2015年4月16日 上午9:40:01
 * 
 */
public class DocumentTask extends RecursiveTask<Integer> {

	/**
	 * 
	 */
	private static final long serialVersionUID = -8108443488083299650L;

	private String documnet[][];

	private int start, end;
	private String word;

	public DocumentTask(String[][] ducumnet, int start, int end, String word) {
		super();
		this.documnet = ducumnet;
		this.start = start;
		this.end = end;
		this.word = word;
	}

	@Override
	protected Integer compute() {
		int result = 0;
		if (end - start < 10) {
			result = processLines(documnet, start, end, word);
		} else {
			int mid = (start + end) / 2;
			DocumentTask task1 = new DocumentTask(documnet, mid, end, word);
			DocumentTask task2 = new DocumentTask(documnet, mid, end, word);
			invokeAll(task1, task2);
			try {
				result = groupResults(task1.get(), task2.get());
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	private Integer groupResults(Integer integer, Integer integer2) {
		Integer result;
		result=integer+integer2;
		return result;
	}

	private Integer processLines(String[][] documnet , int start , int end , String word ) {
		//为任务所要处理的每一航,创建一个LineTask对象,然后存储在任务列表里
		List<LineTask> tasks=new LinkedList<LineTask>();
		for(int i=start;i<end;i++){
			LineTask task=new LineTask(documnet[i],0,documnet[i].length,word);
			tasks.add(task);
		}
		invokeAll(tasks);
		int result=0;
		for(int i=0;i<tasks.size();i++){
			LineTask task= tasks.get(i);
			try {
				result=result+task.get();
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}
					
		}
		return new Integer(result);
	}

}
package com.xingfu.wx_2;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.RecursiveTask;

/**
 * 
 * @author W,x
 * @version 创建时间:2015年4月16日 上午9:55:34
 * 
 */
public class LineTask extends RecursiveTask<Integer> {

	/**
	 * 
	 */
	private static final long serialVersionUID = -986700472084679093L;

	private String line[];
	private int start, end;
	private String word;

	public LineTask(String[] line, int start, int end, String word) {
		super();
		this.line = line;
		this.start = start;
		this.end = end;
		this.word = word;
	}

	@Override
	protected Integer compute() {
		Integer result = null;
		if (end - start < 100) {
			result = count(line, start, end, word);
		} else {
			int mid = (start + end) / 2;
			LineTask task1 = new LineTask(line, start, mid, word);
			LineTask task2 = new LineTask(line, mid, end, word);
			invokeAll(task1, task2);
			try {
				//计算两个任务返回的值相加
				result = groupReuslts(task1.get(), task2.get());
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	private Integer count(String[] line2, int start2, int end2, String word) {
		int counter;
		counter = 0;
		for (int i = start; i < end; i++) {
			if (line[i].equals(word)) {
				counter++;
			}
		}
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return counter;
	}

	private Integer groupReuslts(Integer integer, Integer integer2) {
		Integer result;
		result = integer + integer2;
		return result;
	}

}

package com.xingfu.wx_2;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;

import com.xingfu.wx.Utils;

/**
 * 
 * @author W,x
 * @version 创建时间:2015年4月16日 上午10:06:28
 * 
 */
public class Main {
	public static void main(String[] args) {
		Document mock = new Document();
		String[][] document = mock.generateDocument(100, 1000, "the");
		// 创建一个DocumentTask 用来更新整个文档,起始0,结束100
		DocumentTask task = new DocumentTask(document, 0, 100, "the");
		ForkJoinPool pool = new ForkJoinPool();
		pool.execute(task);

		do {
			System.out.println("**********************************************************\n");
			Utils.print("Main : Parallelism  : %d\n", pool.getParallelism());
			Utils.print("Main : Active Threads : %d\n", pool.getActiveThreadCount());
			Utils.print("Main: Task Count : %d\n", pool.getQueuedTaskCount());
			Utils.print("Main: Steal Count : %d\n", pool.getStealCount());
			System.out.println("**********************************************************\n");
			try {
				TimeUnit.SECONDS.sleep(1);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		} while (!task.isDone());
		//关闭线程池
		pool.shutdown();
		//等待线程结束
		try {
			pool.awaitTermination(1, TimeUnit.DAYS);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		try {
			Utils.print("Main :The work appears %d in the document ", task.get());
		} catch (InterruptedException | ExecutionException e) {
			e.printStackTrace();
		}
	}
}

工作原理

DocumentTask类:这个类的任务需要处理由start和end属性决定的文档行。如果这些行数小于10,那么,就每行创建一个LineTask类对象,然后在任务执行结束后,合计返回的结果,并返回总数。如果任务要处理的行数大于10,那么,将任务拆分成两组,并创建两个DocumentTask对象处理这两组对象。当这些任务执行结束后,同样合计返回的结果,并返回总数。

LineTask类:这个类的任务需要处理文档中的某一组词,如果一组词的个数小于100,那么任务将直接在这一组词里搜索特定词,然后返回查找词在这一组词中出现的次数。否则,任务将拆分这些词为两组,并创建两个LineTask对象来处理这两组词。当这些任务执行完成后,合计返回的结果,并返回总数。

在Main主类中,我们通过默认的构造器创建了ForkJoinPool对象,然后执行Document类,来处理一个共有100行,每行1000字的文档,这个任务将问题拆分成DocumentTask对象和LineTask对象,然后当所有的任务执行完成后,使用原始的任务来获取整个文档中所要查找的词出现的次数,由于任务继承了RecursiveTask类,因此能够返回结果

调用get()方法来获得Task返回的结果,这个方法声明在Future接口里,并由RecursiveTask类实现。

执行程序时,在控制台上,我们可以比较一行与最后一航的输出信息,第一行文档生成时被查找的词出现的次数,最后一行则是通过Forl/join任务计算而来的被查找的词出现的次数,并且这两个数字相同

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值