一。概览
1.fork/join体现了“分而治之”,框架的原理也是分而治之,就是将一个大任务,进行拆分成若干个小任务,再将一个个的小任务运算的结果进行join汇总
所谓的分而治之是:一个大问题分割成多个相同的小问题,并且小问题之间无关联
对应的动态规划是:一个大问题分割成多个相同的小问题,并且小问题之间有关联
2.fork/join使用标准范式:
1.new ForkJoinPool
2.new MyTask或者MyAction task继承RecursiveTask<Integer> action继承RecursiveAction
3.pool.invoke(task);
3.fork/join使用说明
需要返回值的用Task 不需要返回值的用Action 标准范式第二步骤 Task继承RecursiveTask<Integer> Action继承RecursiveAction
同步用invoke,异步用submit或者execute 标准范式第三步骤
二。案例
1. 统计整型数组中所有元素的和
常规做法:单线程遍历累加
public class SumNormal {
public static void main(String[] args) {
int count = 0;
int[] src = MakeArray.makeArray();
long start = System.currentTimeMillis();
for(int i= 0;i<src.length;i++){
SleepTools.ms(1);
count = count + src[i];
}
System.out.println("The count is "+count
+" spend time:"+(System.currentTimeMillis()-start)+"ms");
}
}
fork/join多线程做法:
1.定义fork/join任务重写compute()方法(因为有返回值所以是Task,无返回值action)
private static class SumTask extends RecursiveTask<Integer>{
private final static int THRESHOLD = MakeArray.ARRAY_LENGTH/10;
private int[] src;
private int fromIndex;
private int toIndex;
public SumTask(int[] src, int fromIndex, int toIndex) {
this.src = src;
this.fromIndex = fromIndex;
this.toIndex = toIndex;
}
@Override
protected Integer compute() {
if (toIndex - fromIndex < THRESHOLD){
System.out.println(" from index = "+fromIndex
+" toIndex="+toIndex);
int count = 0;
for(int i= fromIndex;i<=toIndex;i++){
SleepTools.ms(1);
count = count + src[i];
}
return count;
}else{
int mid = (fromIndex+toIndex)/2;
SumTask left = new SumTask(src,fromIndex,mid);
SumTask right = new SumTask(src,mid+1,toIndex);
invokeAll(left,right);
return left.join()+right.join();
}
}
}
2.主线程
public static void main(String[] args) {
int[] src = MakeArray.makeArray();
ForkJoinPool pool = new ForkJoinPool();
SumTask sumTask= new SumTask(src,0,src.length-1);
pool.invoke(sumTask);
System.out.println("The count is "+sumTask.join());
}
public class MakeArray {
public static final int ARRAY_LENGTH = 3000;
public final static int THRESHOLD = 47;
public static int[] makeArray() {
Random r = new Random();
int[] result = new int[ARRAY_LENGTH];
for(int i=0;i<ARRAY_LENGTH;i++){
result[i] = r.nextInt(ARRAY_LENGTH*3);
}
return result;
}
}
2 遍历指定目录(含子目录)找寻指定类型文件
1.定义fork/join任务重写compute()方法(因为无返回值所以是action,有返回值task)
public class FindDirsFiles extends RecursiveAction {
private File path;
public FindDirsFiles(File path) {
this.path = path;
}
@Override
protected void compute() {
List<FindDirsFiles> subTasks = new ArrayList<>();
File[] files = path.listFiles();
if (files!=null){
for (File file : files) {
if (file.isDirectory()) {
subTasks.add(new FindDirsFiles(file));
} else {
if (file.getAbsolutePath().endsWith("txt")){
System.out.println("文件:" + file.getAbsolutePath());
}
}
}
if (!subTasks.isEmpty()) {
for (FindDirsFiles subTask : invokeAll(subTasks)) {
subTask.join();
}
}
}
}
}
2.主线程
public static void main(String [] args){
try {
ForkJoinPool pool = new ForkJoinPool();
FindDirsFiles task = new FindDirsFiles(new File("F:/"));
pool.execute(task);
System.out.println("Task is Running......");
Thread.sleep(1);
int otherWork = 0;
for(int i=0;i<100;i++){
otherWork = otherWork+i;
}
System.out.println("Main Thread done sth......,otherWork="
+otherWork);
task.join();
System.out.println("Task end");
} catch (Exception e) {
e.printStackTrace();
}
}