ForkJoinPool源码解析(三)-- join

public final V join() {
        int s;
        if ((s = doJoin() & DONE_MASK) != NORMAL)
            reportException(s);//可能被取消或发生异常
        return getRawResult();
    }
 
private int doJoin() {
        int s; Thread t; ForkJoinWorkerThread wt; ForkJoinPool.WorkQueue w;
        return (s = status) < 0 ? s :
            ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ?
            (w = (wt = (ForkJoinWorkerThread)t).workQueue).
            tryUnpush(this) && (s = doExec()) < 0 ? s :
            wt.pool.awaitJoin(w, this, 0L) :
            externalAwaitDone();
        //是否已执行完
            //是 直接返回任务状态
            //否 当前线程是否是ForkJoinWorkerThread
                    //是 执行workQueue的tryUnPush方法和doExec方法。这里的意思是移除在top的当前任务,然后自己主动执行
                        //移除成功 返回任务状态
                        //移除失败 调用awaitJoin方法
                    //否 执行externalAwaitDone
    }
 
final int awaitJoin(WorkQueue w, ForkJoinTask<?> task, long deadline) {
        int s = 0;
        if (task != null && w != null) {
            //将当前任务变为队列的正在join的任务,先前的放到task的pervJoin,形成一个栈。
            ForkJoinTask<?> prevJoin = w.currentJoin;
            U.putOrderedObject(w, QCURRENTJOIN, task);
            CountedCompleter<?> cc = (task instanceof CountedCompleter) ?
                (CountedCompleter<?>)task : null;
            for (;;) {
                //小于0说明完成
                if ((s = task.status) < 0)
                    break;
                //CountedCompleter任务由helpComplete来完成join
                if (cc != null)
                    helpComplete(w, cc, 0);
                //如果队列为空或 执行任务没有成功则会去帮助偷窃.
                        //执行失败说明任务被偷了。
                //tryRemoveAndExec任务执行成功则会返回false
                //在当前队列任务执行完了或者
                    // 或者(在队列中没有找到这个任务且任务没有执行)
                //则这个任务是被偷了,偷窃任务的可能是在join。
                //所以去帮助偷窃者执行他的任务。
                else if (w.base == w.top || w.tryRemoveAndExec(task))
                    helpStealer(w, task);
                //如果任务执行成功则会跳出循环
                if ((s = task.status) < 0)
                    break;
                long ms, ns;
                if (deadline == 0L)
                    ms = 0L;
                else if ((ns = deadline - System.nanoTime()) <= 0L)
                    break;
                else if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) <= 0L)
                    ms = 1L;
                //尝试补偿,在里面有进行
                if (tryCompensate(w)) {
                    //等待
                    task.internalWait(ms);
                    //活跃线程加1
                    U.getAndAddLong(this, CTL, AC_UNIT);
                }
            }
            //还原当前队列正在join的任务
            U.putOrderedObject(w, QCURRENTJOIN, prevJoin);
        }
        //返回任务的状态
        return s;
    }

  join这个方法我跟代码了,但是还是,唯一还算理解的就是join的task会形成一个栈。每个task都会执行fork,每次fork都会往自己的workqueue的task数组把自己方法进去。

然后在执行join的时候又会把自己弹出来  tryUnpush(this) 。依次执行并形成join栈。这样当任务拆解到足够小的时候,执行join就会返回了,这样它之前的任务也会返回了。

  1.  

posted on 2021-01-06 18:19  MaXianZhe  阅读(284)  评论(1编辑  收藏  举报

导航