为什么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

回到顶部