也即是,现有ForkJoinTask的子类exec方法,均是返回true,而只有CountedCompleter返回false,所以其需要设置正常结束状态,任务才会被结算成执行完毕,在任务fork等调用时,才会结束阻塞;如果你只是往里面添加一个任务这个则不处理也没有关系
类似RecursiveAction的效果
class Task(private val num : Int,private val end : Int, completer: Task? = null) : CountedCompleter(completer) {
override fun compute() {
if (end == num) {
if (end % 2 == 0) println(“odd $end”)
propagateCompletion()
return
}
addToPendingCount(1)
val middle = (num + end) / 2
Task(num, middle, this).fork()
Task(middle + 1, end,this).fork()
}
}
类似RecursiveTask的效果
class Task(val num : Int,val end : Int, completer: Task? = null) : CountedCompleter(completer) {
@Volatile public var mResult = 0
private var t1 : Task? = null
private var t2 : Task? = null
override fun compute() {
if (end == num) {
mResult = end
tryComplete()
return
}
addToPendingCount(1)
val middle = (num + end) / 2
t1 = Task(num, middle, this).fork() as Task
t2 = Task(middle + 1, end,this).fork() as Task
}
override fun onCompletion(caller: CountedCompleter<*>?) {
if (this != caller && caller is Task) {
mResult = (t1?.mResult ?: 0) + (t2?.mResult ?: 0)
}
}
override fun getRawResult(): Int {
return mResult
}
override fun setRawResult(t: Int?) {
mResult = t ?: 0
}
}
如果不通过根任务的join等方法获取结果,而是其它数据交流的办法(Rxjava 中发射、LiveData等),则可以不重写get/setRawResult方法
某个特殊结果寻找
class Task(val num : Int,val end : Int, completer: Task? = null) : CountedCompleter(completer) {
@Volatile public var mResult = 0
override fun compute() {
if (end % 7 == 0 && end % 5 == 0) {
(root as Task).mResult = end
quietlyCompleteRoot()
return
} else if (num == end) {
return
}
addToPendingCount(1)
val middle = (num + end) / 2
Task(num, middle, this).fork()
Task(middle + 1, end,this).fork()
}
override fun getRawResult(): Int {
return mResult
}
override fun setRawResult(t: Int?) {
mResult = t ?: 0
}
}
可能还有其它场景,但是这些场景的处理都是依据pending值和其引用来确定是否设置结束状态;
- 原子操作设置值:addToPendingCount、compareAndSetPendingCount等方法
- 利用设置状态方法来处理:propagateCompletion、tryComplete、quietlyCompleteRoot等
3 原理实现
ForkJoinPool线程池,其执行任务的线程对象是ForkJoinWorkerThread子类,任务均被包装为ForkJoinTask的子类
3.1 ForkJoinWorkerThread类
Thread子类,其中主要内容有:线程队列创建、销毁、执行
3.1.1 线程队列创建
在构造器中通过ForkJoinPool.registerWorker方法为当前线程关联队列,队列位置为线程池队列数组的奇数位置
3.1.2 线程的销毁
通过ForkJoinPool.deregisterWorker方法进行销毁
3.1.4 线程的运行
run方法内为其主要逻辑,不贴代码了;需要在其线程队列建立后,持有数据还未申请空间之前进行线程执行,否则不做任何处理
回调方法onStart,表示线程开始执行;通过ForkJoinPool.runWorker方法来执行任务;onTermination回调方法接收异常处理;
3.2 ForkJoinTask类
抽象类,实现了Future、Serializable接口;其主要内容:任务异常收集、fork-join执行流程(join也可以是invoke、get等操作,但这里就依据join来讲解)
task有以下几种状态
volatile int status;
static final int DONE_MASK = 0xf0000000;
static final int NORMAL = 0xf0000000;
static final int CANCELLED = 0xc0000000;
static final int EXCEPTIONAL = 0x80000000;
static final int SIGNAL = 0x00010000;
static final int SMASK = 0x0000ffff;
- NORMAL:结束状态,正常结束,负数
- CANCELLED:结束状态,用户取消,负数
- EXCEPTIONAL:结束状态,执行异常,负数
- SIGNAL:等待通知执行状态,正数
- 0 : 起始状态
3.2.1 异常收集
异常数据收集,是根据弱引用机制来处理;弱引用任务节点结构如下:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
资源分享
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。
2020年虽然路途坎坷,都在说Android要没落,但是,不要慌,做自己的计划,学自己的习,竞争无处不在,每个行业都是如此。相信自己,没有做不到的,只有想不到的。祝大家2021年万事大吉。
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
ndroid移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算**