(1)任务执行
1.invoke
同步执行,也就是说调用之后需要等待任务完成,才能执行后面的代码
@Test
public void test() throws InterruptedException {
ForkJoinPool forkJoinPool = new ForkJoinPool();
// 生成一个计算任务,负责计算1+2+...+8
CalculateTask task = new CalculateTask(1, 8);
// 执行一个任务
int result = forkJoinPool.invoke(task);
forkJoinPool.shutdown();
System.out.println(result);
}
计算任务
import java.util.concurrent.ExecutionException;
import java.util.concurrent.RecursiveTask;
public class CalculateTask extends RecursiveTask<Integer>{//因为需要返回值,所以使用RecursiveTask
private static final long serialVersionUID = -8486729149866588744L;
private static final int THRESHOLD = 2;// 阈值
private int start;
private int end;
public CalculateTask(int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
int sum = 0;
if (end-start<THRESHOLD) {//分解为2个数的和然后计算
for(;start<=end;start++){
sum += start;
}
}else {
int mid = (start + end) >>> 1;
System.out.println("Task: Pending tasks:"+getQueuedTaskCount());
System.out.println("thread1 add range from "+start+" to "+(mid-1)
+" ; "
+"thread2 add range from "+(mid+1)+" to "+end);
RecursiveTask<Integer> task1 = new CalculateTask(start, mid);
RecursiveTask<Integer> task2 = new CalculateTask(mid+1, end);
invokeAll(task1,task2);
try {
sum = task1.get()+task2.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
return sum;
}
}
结果为:
Task: Pending tasks:0
thread1 add range from 1 to 3 ; thread2 add range from 5 to 8
Task: Pending tasks:1
thread1 add range from 1 to 1 ; thread2 add range from 3 to 4
Task: Pending tasks:0
thread1 add range from 5 to 5 ; thread2 add range from 7 to 8
36
也就是说,在任务执行完之后,才会打印结果
2.submit/execute
异步执行,只有在Future调用get的时候会阻塞
@Test
public void test() throws InterruptedException {
ForkJoinPool forkJoinPool = new ForkJoinPool();
// 生成一个计算任务,负责计算1+2+..+800
CalculateTask task = new CalculateTask(1, 800);
// 执行一个任务
Future<Integer> result = forkJoinPool.submit(task);
TimeUnit.MILLISECONDS.sleep(1);
System.out.println("task已经提交");
forkJoinPool.shutdown();
try {
System.out.println(result.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
部分结果为:
thread1 add range from 220 to 220 ; thread2 add range from 222 to 222
task已经提交
Task: Pending tasks:5
Task: Pending tasks:3
Task: Pending tasks:2
thread1 add range from 8 to 8 ; thread2 add range from 10 to 10
可见,任务和主线程是异步执行的
(2)判断任务是否执行完毕
1.从Task角度
可以通过isDone方法来进行判断。
如果有多个任务,循环判断即可,结果也是这样
public static void main(String[] args) throws Exception {
Path p = Paths.get("D:/");
List<Path> roots = (List<Path>) FileSystems.getDefault().getRootDirectories();
List<Path> result = new ArrayList<>(); //所有Task结果
List<MyTask> tasks = new ArrayList<>(); //task数组
ForkJoinPool pool = new ForkJoinPool();
for(Path root:roots) {
MyTask t = new MyTask(root, "pdf");
pool.execute(t);
tasks.add(t);
}
System.out.print("正在处理中");
while(isAllDone(tasks) == false) {
System.out.print(". ");
TimeUnit.SECONDS.sleep(3);
}
for(MyTask t:tasks) {
result.addAll(t.get());
}
for(Path pp:result) {
System.out.println(pp);
}
}
private static boolean isAllDone(List<MyTask> tasks) { //判断所有任务是否都执行结束
boolean result = true;
for(MyTask t:tasks) {
if(t.isDone() == false) {
result = false;
break;
}
}
return result;
}
2.从ForkJoinPool角度
可以通过awaitTermination()来判断
其中可以定义过期时间,如果超时就不再等待