1. FolkJoinPool概念
该线程池主要用来分叉任务再汇总任务处理,提高处理速度;每个任务都有自己的任务队列;线程池采用了分而治之的编程思想。
流程编程中的parallelStream内部就使用了forkJoinPool来实现;
2. invoke方法和execute方法区别
execute方法开启异步执行,没有返回值,执行结束后也无法获知;
Invoke方法有返回值,即等待线程结束返回;
3. 使用例子
(1)RecursiveAction无返回值任务
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.atomic.AtomicInteger;
/**
* @author steve
* @Description 生产者玉消费者线程
* @date 2022/4/7 22:30
*/
public class T22_ForkJoinPool {
static int[] nums = new int[1_000_000];
static final int MAX_NUM = 50_000;
static Random ran = new Random();
static AtomicInteger result = new AtomicInteger();
static {
for (int i = 0; i < nums.length; i++) {
nums[i] = ran.nextInt(100);
}
long start = System.currentTimeMillis();
System.out.println("串行执行结果" + Arrays.stream(nums).sum());
long end = System.currentTimeMillis();
System.out.println("串行执行时间:"+(end - start));
}
static class AddTask extends RecursiveAction {
int start, end;
AddTask(int start, int end) {
this.start = start;
this.end = end;
}
@Override
protected void compute() {
if (end - start <= MAX_NUM) {
int sum = 0;
for (int i = start; i < end; i++) {
sum += nums[i];
}
result.addAndGet(sum);
// System.out.println("from:" + start + " to:" + end + " = " + sum);
} else {
int middle = start + (end - start) / 2;
System.out.println("start:"+start+" end:"+end+" middle:"+middle);
AddTask subTask1 = new AddTask(start, middle);
AddTask subTask2 = new AddTask(middle, end);
subTask1.fork();
subTask2.fork();
subTask1.join();//返回执行结果,即等待执行结束
subTask2.join();
}
}
}
public static void main(String[] args) throws IOException, InterruptedException {
ForkJoinPool pool = new ForkJoinPool();
long start = System.currentTimeMillis();
AddTask task = new AddTask(0, nums.length);
pool.invoke(task);// 等价与execute + task.join
//适合没有返回值的任务;
//task.join();
System.out.println(result.get());
long end = System.currentTimeMillis();
System.out.println("并行执行时间:"+(end - start));
}
(2)RecursiveTask有返回值任务
import java.io.IOException;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
/**
* @author steve
* @Description 生产者玉消费者线程
* @date 2022/4/7 22:30
*/
public class T22_ForkJoinPool_2 {
static int[] nums = new int[1_000_000];
static final int MAX_NUM = 50_000;
static Random ran = new Random();
static {
for (int i = 0; i < nums.length; i++) {
nums[i] = ran.nextInt(100);
}
System.out.println("串行执行结果"+ Arrays.stream(nums).sum());
}
static class AddTaskReturn extends RecursiveTask<Integer> {
int start, end;
AddTaskReturn(int start, int end){
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
if (end - start <= MAX_NUM) {
int sum = 0;
for (int i = start; i < end; i++) {
sum += nums[i];
}
return sum;
// System.out.println("from:" + start + " to:" + end + " = " + sum);
} else {
int middle = start + (end - start) / 2;
AddTaskReturn subTask1 = new AddTaskReturn(start, middle);
AddTaskReturn subTask2 = new AddTaskReturn(middle, end);
subTask1.fork();
subTask2.fork();
return subTask1.join() + subTask2.join();
}
}
}
public static void main(String[] args) throws IOException, InterruptedException {
ForkJoinPool pool = new ForkJoinPool();
AddTaskReturn task = new AddTaskReturn(0, nums.length);
pool.execute(task);
int result = task.join();
System.out.println(result);
}
}