package helloJava;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
public class ForkJoinTask extends RecursiveTask<Long> {
private static final long serialVersionUID = 4156326396802212970L;
private static final long MAX = 1000000000L; // 总循环数
private static final long THRESHOLD = 600L; // 这个值其实是最后拆解子任务的循环数
private long start;
private long end;
public ForkJoinTask(long start, long end) {
this.start = start;
this.end = end;
}
public static void main(String[] args) {
test();
System.out.println("--------------------");
testForkJoin();
}
private static void test() {
System.out.println("test");
long start = System.currentTimeMillis();
Long sum = 0L;
for (long i = 0L; i <= MAX; i++) {// 直接全部循环
sum += i;
}
System.out.println(sum);
System.out.println(System.currentTimeMillis() - start + "ms");
}
private static void testForkJoin() {
System.out.println("testForkJoin");
long start = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
Long sum = forkJoinPool.invoke(new ForkJoinTask(1, MAX));// 需要等待返回结果
System.out.println(sum);
System.out.println(System.currentTimeMillis() - start + "ms");
}
@Override
protected Long compute() {
long sum = 0;
if (end - start <= THRESHOLD) {// 拆解小于最小任务数,直接循环计算
for (long i = start; i <= end; i++) {
sum += i;
}
return sum;
} else { //大于最小循环数,继续平均拆解
long mid = (start + end) / 2;
ForkJoinTask task1 = new ForkJoinTask(start, mid);
task1.fork();
ForkJoinTask task2 = new ForkJoinTask(mid + 1, end);
task2.fork();
return task1.join() + task2.join(); //汇总子任务计算结果
}
}
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
public class ForkJoinTask extends RecursiveTask<Long> {
private static final long serialVersionUID = 4156326396802212970L;
private static final long MAX = 1000000000L; // 总循环数
private static final long THRESHOLD = 600L; // 这个值其实是最后拆解子任务的循环数
private long start;
private long end;
public ForkJoinTask(long start, long end) {
this.start = start;
this.end = end;
}
public static void main(String[] args) {
test();
System.out.println("--------------------");
testForkJoin();
}
private static void test() {
System.out.println("test");
long start = System.currentTimeMillis();
Long sum = 0L;
for (long i = 0L; i <= MAX; i++) {// 直接全部循环
sum += i;
}
System.out.println(sum);
System.out.println(System.currentTimeMillis() - start + "ms");
}
private static void testForkJoin() {
System.out.println("testForkJoin");
long start = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
Long sum = forkJoinPool.invoke(new ForkJoinTask(1, MAX));// 需要等待返回结果
System.out.println(sum);
System.out.println(System.currentTimeMillis() - start + "ms");
}
@Override
protected Long compute() {
long sum = 0;
if (end - start <= THRESHOLD) {// 拆解小于最小任务数,直接循环计算
for (long i = start; i <= end; i++) {
sum += i;
}
return sum;
} else { //大于最小循环数,继续平均拆解
long mid = (start + end) / 2;
ForkJoinTask task1 = new ForkJoinTask(start, mid);
task1.fork();
ForkJoinTask task2 = new ForkJoinTask(mid + 1, end);
task2.fork();
return task1.join() + task2.join(); //汇总子任务计算结果
}
}
}
从结果看出,并行的时间损耗明显要少于串行的,这就是并行任务的好处。
尽管如此,在使用Fork/Join时也得注意,不要盲目使用。
如果任务拆解的很深,系统内的线程数量堆积,导致系统性能性能严重下降;
如果函数的调用栈很深,会导致栈内存溢出;