之前一直认为forkjoin有自己的线程池,那么执行任务的时候应该是使用池中的线程, 但是在实际运用过程中遇到一些问题,不管是任务是否需要拆分,主线程都会执行任务;
测试demo如下:
public class UpdateTask extends RecursiveTask<Long> {
List<User> list;
static final int THRESHOLD = 2;
int start ;
int end ;
private UserService userService;
public UpdateTask(List<User> list, int start, int end , UserService userService) {
System.out.println("初始化的线程id:"+Thread.currentThread().getName());
this.list = list;
this.start = start;
this.end = end;
this.userService = userService;
}
@Override
protected Long compute() {
System.out.println("分配的线程id:"+Thread.currentThread().getName());
int batchCount = end - start;
if (batchCount<= THRESHOLD){
for (int i = start; i < end; i++) {
User user = list.get(i);
int i1 = user.getAge() + 1;
user.setAge(i1);
userService.updateById(user);
}
System.out.println("执行的线程id:"+Thread.currentThread().getName());
return 0L;
}
int middle = (end+start)/2;
//递归
UpdateTask task1 = new UpdateTask(list,start,middle,userService);
UpdateTask task2 = new UpdateTask(list,middle,end,userService);
invokeAll(task1,task2);
return 0L;
}
}
运行结果如下:
主线程id:http-nio-8001-exec-2
初始化的线程id:http-nio-8001-exec-2
分配的线程id:http-nio-8001-exec-2
初始化的线程id:http-nio-8001-exec-2
初始化的线程id:http-nio-8001-exec-2
分配的线程id:http-nio-8001-exec-2
分配的线程id:ForkJoinPool.commonPool-worker-0
初始化的线程id:ForkJoinPool.commonPool-worker-0
初始化的线程id:ForkJoinPool.commonPool-worker-0
分配的线程id:ForkJoinPool.commonPool-worker-0
分配的线程id:ForkJoinPool.commonPool-worker-9
执行的线程id:http-nio-8001-exec-2
执行的线程id:ForkJoinPool.commonPool-worker-0
执行的线程id:ForkJoinPool.commonPool-worker-9
在网上找了一些资料,说法都是主线程不会参与任务的执行,故有此问
通过反向追踪,定位到源码里面的这一行;
主线程 通过invoke 进入该方法, 有一定几率满足 ForkJoinPool.common.tryExternalUnpush(this) 的条件, 然后弹出的任务由主线程执行