Fork/join框架执行任务并返回结果

来源:互联网 发布:淘宝卖家级别 编辑:程序博客网 时间:2024/06/05 10:06

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;}@Overrideprotected 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;}@Overrideprotected 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,结束100DocumentTask 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
原创粉丝点击