简介
把一个大任务分成一个个小任务,然后合并结果。其中同步用invoke提交,异步用submit(有返回值) excute(无返回值)提交
需求
统计1亿个商品的总数量
demo
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
@Service
public class FkSum {
@Autowired
private DbUtils dbUtils;
private static class SumTask extends RecursiveTask<Long> {
private int startId;
private int endId;
private DbUtils dbUtils;
public SumTask(int startId, int endId, DbUtils dbUtils) {
this.startId = startId;
this.endId = endId;
this.dbUtils = dbUtils;
}
//使用ForkJoinPool调用invoke()时,底层核心调用compute()方法
@Override
protected Long compute() {
//如果满足条数小于 5000
if (endId - startId < SingleThread.THRESHOLD) {
//执行最小粒度任务
return dbUtils.sumRecorders(endId, startId);
} else {
//fromIndex....mid.....toIndex
int mid = (startId + endId) / 2;//折半,将数据分成左右两部分
SumTask left = new SumTask(startId, mid, dbUtils);//左边数据
SumTask right = new SumTask(mid + 1, endId, dbUtils);//右边数据
invokeAll(left, right);//递归调用compute(),是否满足if条件,满足计算,不满足继续拆
long leftResult = left.join();
long rightResult = right.join();
return leftResult + rightResult;
}
}
}
public void sum() {
//核心类
ForkJoinPool pool = new ForkJoinPool(64);
long start = System.currentTimeMillis();
int recordMin = dbUtils.getMin();//从数据库获取最小ID号
int recordMax = dbUtils.getMax();//从数据库获取最大ID号
SumTask sumTask = new SumTask(recordMin,
recordMax, dbUtils);//初始化总任务:1亿数据库查询的任务
pool.invoke(sumTask);//拆分 计算 调用invoke, 实际是执行compute()
System.out.println("Task is Running.....");
System.out.println("The sum is " + sumTask.join()
+ " spend time:" + (System.currentTimeMillis() - start) + "ms");
}
}
dao层
@Service
public class DbUtils {
@Autowired
private MakeArray makeArray;
public int getMin(){
String sql = "select min(id) from goods_info";
Random r = new Random();
return r.nextInt(10)+10;
}
public int getMax(){
String sql = "select max(id) from goods_info";
Random r = new Random();
return r.nextInt(10000000);
}
/**
* @param sql 要执行的sql
* @param length 限定的记录条数
* @return
*/
public int[] getRecords(String sql,int length){
try {
Thread.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
return makeArray.makeArray(length);
}
/**
* 在数据库中获得指定数目的记录,然后进行累加
* @param fromId 记录开始id
* @param toId 记录结束id
* @return 累积的和
*/
public long sumRecorders(int fromId,int toId){
long sum = 0;
String sql = "select goods_count from goods_info where id >= "+fromId
+" and id < "+toId;
try {
Thread.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
//当前批次商品的数量
int[] result = makeArray.makeArray(SingleThread.THRESHOLD);
for(int record:result){
sum = sum + record;
}
return sum;
}
}