【七彩虹教育】一个归并任务的流转

2025-05-21ASPCMS社区 - fjmyhfvclm

Step1. ️任务提交到任务队列

包括 invoke 等所有任务提交方法最终都会调用 ForkJoinPool.externalPush 方法。

️这里面需要考虑将任务提交到哪个队列?

如果提交到 ForkJoinWorkerThread 自己的双端任务队列中:不管提交到头还是尾,都会和我们上面分析的三个操作发生任务冲突。而且如何选择负载最小的线程来提交也会增加问题复杂性。

ForkJoinPool 中双端任务队列是用数组(volatile WorkQueue[] workQueues)实现的,其中奇数下标存放的是可激活的任务队列,偶数下标存放的是不可激活的任务队列。激活指的是这个队列是否是某个ForkJoin线程的任务队列。

ForkJoinPool.externalPush 只能将任务提交到不可激活任务队列,该方法的主要逻辑为:

当提交的任务是 pool 的第一个任务时,会初始化 workQueues,ForkJoinWorkerThread 等资源,通过 hash 算法选择一个偶数下标的 workQueue,在 TOP 处放入任务。同时唤醒 ForkJoinWorkerThread 开始拉取任务工作。

当提交的任务不是第一个任务,此时 workQueues 等资源已初始化好。同样需要选择一个偶数下标的 workQueue 存放任务,如果选中的 workQueue 只有这一个任务,说明之前线程资源大概率是闲置的状态,会尝试 ️唤醒(signalWork 方法) 一个空闲的 ForkJoinWorkerThread 开始拉取任务工作。

全部评论