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   MaXianZhe  阅读(304)  评论(1编辑  收藏  举报

编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示