并发编程:fork/join框架:2、合并任务的执行结果(RecursiveTask)!!!

目录

 

RecursiveTask

案例说明

一、主程序

二、文档工厂

三、文档统计任务

四、行统计任务

五、处理结果


RecursiveTask

ForkJoinTask的子类,该类可以返回执行结果。

案例说明

模拟一个文档,在文档中查找匹配单词的数量。该功能分为两步:

  1. 文档任务,在文档中的一个行集合中查找单词数量。
  2. 行任务,在文档的一行中查找单词数量。

一、主程序

package xyz.jangle.thread.test.n5_3.recursivetask;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;

/**
 * 	5.3、合并任务的执行结果
 * 	模拟一个文档,在文档中查找匹配单词的数量。
 * 	每10行以内作为一个1级任务,该1级任务再细分为每一行的2级任务。
 * 
 * @author jangle
 * @email jangle@jangle.xyz
 * @time 2020年8月27日 下午6:13:34
 * 
 */
public class M {

	public static void main(String[] args) {
		DocumentMock mock = new DocumentMock();
		String[][] document = mock.generateDocument(100, 10000, "java");
		DocumentTask task = new DocumentTask(document, 0, 100, "java");
		// 获取默认的ForkJoinPool
		ForkJoinPool pool = ForkJoinPool.commonPool();
		pool.execute(task);
		do {
			System.out.println("***********************");
			System.out.println("Main:Active Thread活跃的线程数:" + pool.getActiveThreadCount());
			System.out.println("Main:Task Count任务数:" + pool.getQueuedTaskCount());
			System.out.println("Main:Steal Count线程窃取数量:" + pool.getStealCount());
			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 {
			System.out.println("Main:单词统计结果:" + task.get());
		} catch (InterruptedException | ExecutionException e) {
			e.printStackTrace();
		}

	}

}

二、文档工厂

package xyz.jangle.thread.test.n5_3.recursivetask;

import java.util.Random;

/**
 * 	模拟文档的工厂
 * @author jangle
 * @email jangle@jangle.xyz
 * @time 2020年8月27日 下午6:14:07
 * 
 */
public class DocumentMock {

	private String words[] = { "the", "hello", "goodbye", "packt", "java", "thread", "pool", "random", "class",
			"main" };

	/**
	 * 	生产一个N行M列的单词二维数组(模拟文档)
	 * @param numLines 行数
	 * @param numWords 单词数
	 * @param word     待查找的单词
	 * @return
	 */
	public String[][] generateDocument(int numLines, int numWords, String word) {
		int counter = 0;
		String[][] document = new String[numLines][numWords];
		Random random = new Random();
		for (int i = 0; i < numLines; i++) {
			for (int j = 0; j < numWords; j++) {
				int index = random.nextInt(words.length);
				document[i][j] = words[index];
				if (document[i][j].equals(word)) {
					counter++;
				}
			}
		}
		System.out.println("DocumentMock:匹配的单词数量:"+counter);
		return document;

	}

}

三、文档统计任务

文档统计任务会将任务划分为10行以内的子任务,该子任务还将委托行任务进行处理。

package xyz.jangle.thread.test.n5_3.recursivetask;

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

/**
 * 统计文档中指定单词出现次数的任务类
 * 
 * @author jangle
 * @email jangle@jangle.xyz
 * @time 2020年8月27日 下午6:24:38
 * 
 */
public class DocumentTask extends RecursiveTask<Integer> {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private String[][] document;
	private int start, end;
	private String word;

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

	@Override
	protected Integer compute() {
		Integer result = null;
		if (end - start < 10) {
			// 统计并返回单词数
			result = processLines(document, start, end, word);
		} else {
			// 将其拆分为2个子任务
			int mid = (start + end) / 2;
			DocumentTask task = new DocumentTask(document, start, mid, word);
			DocumentTask task2 = new DocumentTask(document, mid, end, word);
			invokeAll(task, task2);
			try {
				// 汇总子任务的结果
				result = task.get() + task2.get();
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * 统计当前段落中单词匹配的数量(为段落的每一行创建一个任务,查询单词数量并汇总)
	 * 
	 * @param document2
	 * @param start2
	 * @param end2
	 * @param word2
	 * @return
	 */
	private Integer processLines(String[][] document2, int start2, int end2, String word2) {
		ArrayList<LineTask> tasks = new ArrayList<LineTask>();
		for (int i = start2; i < end2; i++) {
			LineTask task = new LineTask(document2[i], 0, document2[i].length, word2);
			tasks.add(task);
		}
		// 执行所有任务
		invokeAll(tasks);
		// 统计任务结果
		int result = 0;
		for (LineTask lineTask : tasks) {
			try {
				result += lineTask.get();
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

}

四、行统计任务

最小的任务处理单元

package xyz.jangle.thread.test.n5_3.recursivetask;

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

/**
 * 统计每一行匹配单词数的任务类
 * 
 * @author jangle
 * @email jangle@jangle.xyz
 * @time 2020年8月27日 下午6:32:42
 * 
 */
public class LineTask extends RecursiveTask<Integer> {

	private static final long serialVersionUID = 1L;

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

	public LineTask(String[] line, int start, int end, String word) {
		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 {
			// 拆分为2个子任务
			int middle = (start + end) / 2;
			LineTask task1 = new LineTask(line, start, middle, word);
			LineTask task2 = new LineTask(line, middle, end, word);
			invokeAll(task1, task2);
			try {
				// 将子任务的结果汇总
				result = task1.get() + task2.get();
			} catch (InterruptedException | ExecutionException e) {
				e.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * 统计指定部分单词匹配的数量
	 * 
	 * @param line2
	 * @param start2
	 * @param end2
	 * @param word2
	 * @return
	 */
	private Integer count(String[] line2, int start2, int end2, String word2) {
		Integer count = 0;
		for (int i = start2; i < end2; i++) {
			if (line2[i].equals(word2)) {
				count++;
			}
		}
		try {
			TimeUnit.MILLISECONDS.sleep(10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return count;
	}

}

五、处理结果

DocumentMock:匹配的单词数量:100371
***********************
Main:Active Thread活跃的线程数:1
Main:Task Count任务数:0
Main:Steal Count线程窃取数量:0
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:56
Main:Steal Count线程窃取数量:0
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:51
Main:Steal Count线程窃取数量:0
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:54
Main:Steal Count线程窃取数量:0
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:47
Main:Steal Count线程窃取数量:0
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:39
Main:Steal Count线程窃取数量:0
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:34
Main:Steal Count线程窃取数量:0
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:40
Main:Steal Count线程窃取数量:0
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:28
Main:Steal Count线程窃取数量:0
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:57
Main:Steal Count线程窃取数量:1
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:36
Main:Steal Count线程窃取数量:1
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:41
Main:Steal Count线程窃取数量:1
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:32
Main:Steal Count线程窃取数量:1
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:40
Main:Steal Count线程窃取数量:6
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:50
Main:Steal Count线程窃取数量:8
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:42
Main:Steal Count线程窃取数量:8
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:40
Main:Steal Count线程窃取数量:8
***********************
Main:Active Thread活跃的线程数:6
Main:Task Count任务数:36
Main:Steal Count线程窃取数量:15
***********************
Main:Active Thread活跃的线程数:6
Main:Task Count任务数:29
Main:Steal Count线程窃取数量:15
***********************
Main:Active Thread活跃的线程数:7
Main:Task Count任务数:21
Main:Steal Count线程窃取数量:20
Main:单词统计结果:100371

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值