这篇文章主要介绍了Android中的Coroutine协程原理是什么,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。协程是一个并发方案。也是一种思想。传统意义上的协程是单线程的,面对io密集型任务他的内存消耗更少,进而效率高。但是面对计算密集型的任务不如多线程并行运算效率高。不同的语言对于协程都有不同的实现,甚至同一种语言对于不同平台的操作系统都有对应的实现。我们kotlin语言的协程是 coroutines for jvm的实现方式。底层原理也是利用java 线程。1.网络上没有详细的关于协程的概念定义,每种语言、每个系统对其实现都不一样。可谓是众说纷纭,什么内核态用户态巴拉巴拉,很容易给我们带偏2.kotlin的各种语法糖对我们造成的干扰。如:高阶函数源码实现类找不到所以扎实的kotlin语法基本功是学习协程的前提。实在看不懂得地方就反编译为java,以java最终翻译为准。kotlin中的协程干的事就是把异步回调代码拍扁了,捋直了,让异步回调代码同步化。除此之外,没有任何特别之处。创建一个协程,就是编译器背后偷偷生成一系列代码,比如说状态机。通过挂起和恢复让状态机状态流转实现把层层嵌套的回调代码变成像同步代码那样直观、简洁。它不是什么线程框架,也不是什么高深的内核态,用户态。它其实对于咱们安卓来说,就是一个关于回调函数的语法糖。。。本文将会围绕挂起与恢复彻底剖析协程的实现原理再Kotlin中函数是一等公民,有自己的类型函数类型函数引用咋都一样?没办法,就这样规定的。使用的时候 只能靠编译器推断带Receiver的写法绑定receiver的函数引用:额外知识点函数作为参数传递Lambda就是匿名函数,它跟普通函数比是没有名字的,听起来好像是废话函数跟匿名函数看起来没啥区别,但是反编译为java后还是能看出点差异如果只是用普通的函数,那么他跟普通java 函数没啥区别。比如 fun a()
就是对应java方法public void a(){}
但是如果通过函数引用(:: a)来用这个函数,那么他并不是直接调用fun a()
而是重新生成一个Function0suspend 修饰。挂起函数中能调用任何函数。非挂起函数只能调用非挂起函数。换句话说,suspend函数只能在suspend函数中调用。简单的挂起函数展示:挂起函数特殊在哪?这下理解suspend为啥只能在suspend里面调用了吧?想要让道貌岸然的suspend函数干活必须要先满足它!!!就是给它里面塞入一颗球。然后他想调用其他的suspend函数,只需将球继续塞到其它的suspend方法里面。普通函数里没这玩意啊,所以压根没法调用suspend函数。。。读到这里,想必各位会有一些疑问:question1.这不是鸡生蛋生鸡的问题么?第一颗球是哪来的?question2.为啥编译后返回值也变了?question3.suspendFun 如果在协程体内被调用,那么他的球(completion)是谁?以一个最简单的方式启动一个协程。Demo-K1startCoroutine 没有返回值 ,而createCoroutine返回一个Continuation,不难看出是SafeContinuation好像看起来主要的区别就是startCoroutine直接调用resume(Unit),所以不用包装成SafeContinuation,而createCoroutine则返回一个SafeContinuation,因为不知道将会在何时何处调用resume,必须保证resume只调用一次,所以包装为safeContinuationSafeContinuationd的作用是为了确保只有发生免费云主机域名异步调用时才挂起
其实可以简单的理解为kotlin层面的原语,就是返回一个协程体。引用代码Demo-K1首先b 是一个匿名函数,他肯定要被编译为一个FunctionX,同时它还被suspend修饰 所以它肯定跟普通匿名函数编译后不一样。编译后的源码为我们可以看到先是 Function1 var0 = new Function1
创建了一个对象,此时跟协程没关系,这步只是编译器层面的匿名函数语法优化如果直接也是一样会创建Function1 var0 = new Function1
解答question1继续调用createCoroutine再继续createCoroutineUnintercepted ,找到在JVM平台的实现把completion传入,并创建一个新的Function1,作为Continuation返回,这就是创建出来的协程体对象,协程的工作核心就是它内部的状态机,invokeSuspend函数调用 create把completion传入,并创建一个新的Function1,作为Continuation返回,这就是创建出来的协程体对象,协程的工作核心就是它内部的状态机,invokeSuspend函数补充—相关类继承关系解答question2&3已知协程启动会调用协程体的resume,该调用最终会来到BaseContinuationImpl::resumeWith状态机代码截取question3答案出来了,传进去的是create创建的那个continuation最后再来聊聊question2,从上面的代码已经很清楚的告诉我们为啥挂起函数反编译后的返回值变为object了。以hello2为例子,hello2能返回代表挂起的白板,也能返回result。如果返回白板,状态机return,协程挂起。如果返回result,那么hello2执行完毕,是一个没有挂起的挂起函数,通常编译器也会提醒 suspend 修饰词无意义。所以这就是设计需要,没有啥因为所以。最后,除了直接返回结果的情况,挂起函数一定会以resume结尾,要么返回result,要么返回异常。代表这个挂起函数返回了。调用resume意义在于重新回调BaseContinuationImpl的resumeWith,进而唤醒状态机,继续执行协程体的代码。换句话说,我们自定义的suspend函数,一定要利用suspendCoroutine 获得续体,即状态机对象,否则无法实现真正的挂起与resume。我们可以不用suspendCoroutine,用更直接的suspendCoroutineUninterceptedOrReturn也能实现,不过这种方式要手动返回白板。不过一定要小心,要在合理的情况下返回或者不返回,不然会产生很多意想不到的结果而suspendCoroutine则没有这个隐患SafeContinuation的奥秘先回顾一下什么叫真正的挂起,就是getOrThrow返回了“白板”,那么什么时候getOrThrow能返回白板?答案就是result被初始化后值没被修改过。那么也就是说resumeWith没有被执行过,即:block(safe)这句代码,block这个被传进来的函数,执行过程中没有调用safe的resumeWith。原理就是这么简单,cas代码保证关键逻辑的原子性与并发安全继续以Demo-K1为例子,这里假设hello2运行在一条新的子线程,否则仍然是没有挂起。感谢你能够认真阅读完这篇文章,希望小编分享的“Android中的Coroutine协程原理是什么”这篇文章对大家有帮助,同时也希望大家多多支持百云主机,关注百云主机行业资讯频道,更多相关知识等着你来学习!
相关推荐: vue+vue validator怎么实现表单验证功能
今天小编给大家分享一下vue+vue validator怎么实现表单验证功能的相关知识点,内容详细,逻辑清晰,相信大部分人免费云主机域名都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。具体代码…
免责声明:本站发布的图片视频文字,以转载和分享为主,文章观点不代表本站立场,本站不承担相关法律责任;如果涉及侵权请联系邮箱:360163164@qq.com举报,并提供相关证据,经查实将立刻删除涉嫌侵权内容。