为什么forkjoin框架中,主线程会参与任务的执行?
之前一直认为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
在网上找了一些资料,说法都是主线程不会参与任务的执行,故有此问
回答:
通过反向追踪,定位到源码里面的这一行;
private int externalAwaitDone() { int s = ((this instanceof CountedCompleter) ? // try helping
ForkJoinPool.common.externalHelpComplete(
(CountedCompleter<?>)this, 0) :
ForkJoinPool.common.tryExternalUnpush(this) ? doExec() : 0);
if (s >= 0 && (s = status) >= 0) {
boolean interrupted = false;
do {
if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) {
synchronized (this) {
if (status >= 0) {
try {
wait(0L);
} catch (InterruptedException ie) {
interrupted = true;
}
}
else
notifyAll();
}
}
} while ((s = status) >= 0);
if (interrupted)
Thread.currentThread().interrupt();
}
return s;
}
主线程 通过invoke 进入该方法, 有一定几率满足 ForkJoinPool.common.tryExternalUnpush(this) 的条件, 然后弹出的任务由主线程执行
回答:
你可以使用execute 尝试下,invoke 涉及等待,主线程不用岂不是浪费?
以上是 为什么forkjoin框架中,主线程会参与任务的执行? 的全部内容, 来源链接: utcz.com/p/944369.html