当前位置: 首页 > wzjs >正文

百度手机网站优化指南免费查企业信息的平台

百度手机网站优化指南,免费查企业信息的平台,东莞有哪家比较好的网站建设公司,网站设计的基本步骤一、挂起函数源码分析1.编译器转换(CPS 转换)挂起函数,只是比普通的函数多了suspend关键字。有了这个suspend关键字以后,Kotlin编译器就会特殊对待这个函数,将其转换成一个带有Callback的函数,这里的Callba…

一、挂起函数源码分析

1.编译器转换(CPS 转换)

        挂起函数,只是比普通的函数多了suspend关键字。有了这个suspend关键字以后,Kotlin编译器就会特殊对待这个函数,将其转换成一个带有Callback的函数,这里的Callback就是Continuation接口。而这个过程,我们称之为CPS转换
suspend fun fetchData(url: String): String {delay(1000) // 挂起点1val result = api.request(url) // 挂起点2return result
}//编译器会将其转换为带有 Continuation 参数的普通函数,函数签名变为:fun fetchData(url: String, continuation: Continuation<String>): Any?
  • 新增的Continuation<String>参数:本质是一个 “回调对象”,保存了挂起函数暂停时的执行状态(如局部变量、程序计数器、调用栈信息等),用于后续恢复执行。
  • 参数返回值变为Any?:有两种可能结果:
    1. 若函数正常执行完成(未挂起),返回实际结果(如String);
    2. 若函数需要挂起,返回一个特殊标记COROUTINE_SUSPENDED,告知调用者 “当前函数已挂起,需等待后续恢复”。

Continuation是挂起函数状态保存与恢复的核心接口,源码定义简化如下:

interface Continuation<in T> {val context: CoroutineContext // 协程上下文(含调度器等信息)fun resumeWith(result: Result<T>) // 恢复执行的触发方法
}
  • context:保存协程的调度器(Dispatcher)、Job 等信息,决定恢复执行时使用哪个线程。
  • resumeWith:当挂起条件满足(如delay时间到、网络请求返回)时,通过此方法触发挂起函数的恢复,result为挂起期间的执行结果(成功或异常)。

2.状态机实现

        当挂起函数经过反编译以后,它会变成由switch和label组成的状态机结构编译器会生成一个状态枚举(如State),每个状态对应一个挂起点前后的逻辑:
private enum class FetchDataState {INITIAL, // 初始状态(未执行)AFTER_DELAY, // 执行完delay后的状态AFTER_REQUEST // 执行完api.request后的状态
}

同时,函数会被改造为一个状态机处理函数,大致逻辑如下:

fun fetchData(url: String, continuation: Continuation<String>): Any? {// 从continuation中获取或初始化状态机val stateMachine = continuation as? FetchDataStateMachine ?: FetchDataStateMachine(continuation)val context = continuation.contextreturn when (stateMachine.state) {FetchDataState.INITIAL -> {// 第一次执行:处理初始逻辑,调用第一个挂起函数(delay)stateMachine.url = url // 保存局部变量stateMachine.state = FetchDataState.AFTER_DELAY // 更新状态// 调用delay,将当前状态机作为其continuation传递val delayResult = delay(1000, stateMachine)if (delayResult == COROUTINE_SUSPENDED) {return COROUTINE_SUSPENDED // 触发挂起} else {// 若delay未挂起(如时间为0),直接进入下一个状态stateMachine.state = FetchDataState.AFTER_DELAY// 继续执行下一段逻辑(相当于“伪恢复”)fetchData(url, stateMachine)}}FetchDataState.AFTER_DELAY -> {// 从delay恢复后:执行第二个挂起函数(api.request)stateMachine.state = FetchDataState.AFTER_REQUESTval requestResult = api.request(stateMachine.url, stateMachine) // 传递状态机if (requestResult == COROUTINE_SUSPENDED) {return COROUTINE_SUSPENDED // 再次挂起} else {// 若request未挂起,直接进入下一个状态stateMachine.state = FetchDataState.AFTER_REQUESTfetchData(url, stateMachine)}}FetchDataState.AFTER_REQUEST -> {// 从api.request恢复后:返回结果val result = stateMachine.result // 从状态机中取出request的结果stateMachine.continuation.resumeWith(Result.success(result)) // 通知上层恢复null // 执行结束}}
}// 状态机类:保存局部变量和当前状态
private class FetchDataStateMachine(val continuation: Continuation<String>
) : Continuation<String> by continuation {var state: FetchDataState = FetchDataState.INITIALvar url: String = "" // 保存局部变量urlvar result: String = "" // 保存api.request的结果
}
        协程状态机代码:其中,when
表达式实现了协程状态机,而continuation.label 则代表了当前状态机的具体状态,continuation.label 改变一次,就代表了挂起函数被调用了一次;

3.挂起函数触发后的挂起和恢复流程

  1. 编译转换:挂起函数被转换为带Continuation参数的函数,逻辑拆分为状态机。
  2. 初始执行:从INITIAL状态开始,执行到第一个挂起点(如delay)。
  3. 挂起触发:若挂起函数返回COROUTINE_SUSPENDED,当前函数返回该标记,线程释放。
  4. 等待恢复:挂起期间,Continuation(状态机)被保存,等待条件满足(如时间到)。
  5. 恢复执行:条件满足后,Continuation.resumeWith被调用,状态机从上次保存的状态(如AFTER_DELAY)继续执行。
  6. 执行完成:当所有状态执行完毕,通过最上层的Continuation返回结果,整个挂起函数执行结束。

阶段总结

        挂起函数因带有suspend关键字会被 Kotlin 编译器进行 CPS 转换,即转换为带有Continuation参数的普通函数,Continuation作为回调对象保存挂起时的执行状态(如局部变量、调用栈等),函数返回值变为Any?,要么是实际结果,要么是特殊标记COROUTINE_SUSPENDED表示挂起;

        转换后的函数会形成由switchlabel组成的状态机结构,编译器生成对应挂起点的状态枚举,状态机通过when表达式实现状态流转,状态机类保存局部变量和当前状态,每次状态改变代表挂起函数被调用一次;

        其挂起和恢复流程为:编译转换后从INITIAL状态开始执行,到挂起点时若返回COROUTINE_SUSPENDED则触发挂起并释放线程,挂起期间Continuation保存状态等待条件满足,条件满足后通过Continuation.resumeWith恢复执行,状态机从上次保存的状态继续,直至所有状态执行完毕,通过最上层Continuation返回结果。

二、lauch的启动源码分析

        底层都依赖着协程构建器(Coroutine Builder)协程上下文(CoroutineContext)

1.协程启动的入口函数:CoroutionScope.launch

launchCoroutineScope的扩展函数,用于启动一个不返回结果的协程。其源码定义如下:

public fun CoroutineScope.launch(context: CoroutineContext = EmptyCoroutineContext,start: CoroutineStart = CoroutineStart.DEFAULT,block: suspend CoroutineScope.() -> Unit
): Job {// 获取当前协程作用域的上下文val newContext = newCoroutineContext(context)// 创建一个新的协程实例(根据不同的启动模式)val coroutine = if (start.isLazy)LazyStandaloneCoroutine(newContext, block)elseStandaloneCoroutine(newContext, active = true)// 根据启动模式决定是立即执行还是延迟执行coroutine.start(start, coroutine, block)return coroutine
}
  1. context: CoroutineContext
    协程上下文,包含调度器(Dispatcher)、Job、异常处理器等元素。默认值为EmptyCoroutineContext,表示使用父协程的上下文。

  2. start: CoroutineStart
    协程启动模式,枚举类型,主要包括:

    • DEFAULT:立即调度协程执行
    • LAZY:懒启动,需显式调用start()join()触发
    • ATOMIC:立即执行,但在调度前无法取消
    • UNDISPATCHED:立即在当前线程执行,直到第一个挂起点
  3. block: suspend CoroutineScope.() -> Unit
    协程体,是一个挂起函数,可在其中调用其他挂起函数。

2.协程上下文的构建与继承

newCoroutineContext(context)是关键方法,用于合并当前作用域的上下文和用户传入的上下文:

public actual fun CoroutineScope.newCoroutineContext(context: CoroutineContext): CoroutineContext {// 获取当前作用域的上下文(如GlobalScope、lifecycleScope的上下文)val combined = this.coroutineContext + context// 如果没有显式指定Job,则添加一个父Job(确保结构化并发)val debug = if (DEBUG) combined + CoroutineId(COROUTINE_ID.incrementAndGet()) else combinedreturn if (combined[Job] != null) debug else debug + Job()
}

关键点:

  • 上下文合并:通过+操作符合并上下文元素,相同类型的元素后添加的会覆盖前面的(如重复指定 Dispatcher)。
  • 默认 Job:若用户未显式指定 Job,会自动添加一个,确保协程有父子关系,实现结构化并发。

3.协程示例的创建与启动模式

根据start参数的不同,会创建不同类型的协程实例:

val coroutine = if (start.isLazy)LazyStandaloneCoroutine(newContext, block)
elseStandaloneCoroutine(newContext, active = true)

两种协程实现:

  1. LazyStandaloneCoroutine
    用于LAZY模式,协程体不会立即执行,直到调用start()join()

  2. StandaloneCoroutine
    用于其他模式,协程体会立即调度执行。

4.协程的真正启动:coroutine.start()

start()方法是协程执行的核心入口,源码如下:

public fun <R, T> CoroutineStart.invoke(coroutine: R, block: suspend R.() -> T) {when (this) {DEFAULT -> coroutine.startCoroutineCancellable(block, coroutine)ATOMIC -> coroutine.startCoroutine(block, coroutine)UNDISPATCHED -> coroutine.startCoroutineUndispatched(block, coroutine)LAZY -> Unit // 懒启动模式下不执行,等待用户显式调用start()}
}

不同启动模式的差异:

  1. DEFAULT模式
    调用startCoroutineCancellable(),允许在调度前取消协程:

    public fun <T> (suspend () -> T).startCoroutineCancellable(completion: Continuation<T>
    ) {createCoroutineUnintercepted(completion).intercepted().resumeCancellableWith(Result.success(Unit))
    }
    
  2. ATOMIC模式
    调用startCoroutine(),不允许在调度前取消:

    public actual fun <T> (suspend () -> T).startCoroutine(completion: Continuation<T>
    ) {createCoroutineUnintercepted(completion).intercepted().resumeWith(Result.success(Unit))
    }
    
  3. UNDISPATCHED模式
    调用startCoroutineUndispatched(),直接在当前线程执行直到第一个挂起点:

    internal fun <R, T> (suspend R.() -> T).startCoroutineUndispatched(receiver: R,completion: Continuation<T>
    ) {val continuation = createCoroutineUnintercepted(receiver, completion)val context = continuation.contextval uCont = continuation.intercepted()if (context[ContinuationInterceptor] == Dispatchers.Unconfined) {// 无限制调度器:直接在当前线程执行uCont.resumeWith(Result.success(Unit))} else {// 其他调度器:先切换到指定线程再执行with(context) {uCont.resumeWith(Result.success(Unit))}}
    }
    

5.async与launch的源码核心差异

asynclaunch的源码结构相似,但有两个关键区别:

public fun <T> CoroutineScope.async(context: CoroutineContext = EmptyCoroutineContext,start: CoroutineStart = CoroutineStart.DEFAULT,block: suspend CoroutineScope.() -> T
): Deferred<T> {// 创建一个携带结果的协程(继承自Job,但多了结果缓存和await()方法)val newContext = newCoroutineContext(context)val coroutine = if (start.isLazy)LazyDeferredCoroutine(newContext, block)elseDeferredCoroutine<T>(newContext, active = true)coroutine.start(start, coroutine, block)return coroutine
}

差异点:

  1. 返回值类型

    • launch返回Job(只能控制生命周期,无法获取结果)
    • async返回Deferred<T>(继承自Job,但可通过await()获取结果)
  2. 结果缓存
    DeferredCoroutine内部维护了一个Result<T>缓存,确保await()可重复获取结果,且支持多协程并发等待。

阶段总结

        Kotlin 协程的启动依赖于协程构建器和协程上下文,其中CoroutineScope.launch作为入口函数,通过合并当前作用域上下文与用户传入的上下文创建新的协程上下文,若未显式指定 Job 则自动添加以确保结构化并发;

        根据启动模式(如 DEFAULT 立即调度、LAZY 懒启动、ATOMIC 立即执行但调度前不可取消、UNDISPATCHED 立即在当前线程执行至首个挂起点)创建不同的协程实例(如 LazyStandaloneCoroutine 或 StandaloneCoroutine),并通过coroutine.start()触发协程执行,不同启动模式对应不同的执行策略;

        asynclaunch源码结构相似,但async返回继承自 Job 的 Deferred<T>类型,可通过 await () 获取结果,而launch仅返回 Job 用于控制生命周期。


文章转载自:

http://87TpHtSb.yqgbw.cn
http://rAP2iTxR.yqgbw.cn
http://WNVSbhDY.yqgbw.cn
http://jvQC6Aeo.yqgbw.cn
http://dGuBczeJ.yqgbw.cn
http://e1kT9RzV.yqgbw.cn
http://wXuhpN4u.yqgbw.cn
http://Zz4niC4L.yqgbw.cn
http://6koozFhQ.yqgbw.cn
http://DiApvQAu.yqgbw.cn
http://byJQY8uU.yqgbw.cn
http://3msHF9fq.yqgbw.cn
http://v1bXjPRE.yqgbw.cn
http://isXSZ6Gc.yqgbw.cn
http://R18Hjn8o.yqgbw.cn
http://JurG2DZy.yqgbw.cn
http://KV0sTn15.yqgbw.cn
http://WYVBwYJN.yqgbw.cn
http://V8OPgX8g.yqgbw.cn
http://HIuKbRiv.yqgbw.cn
http://oYapdlZ9.yqgbw.cn
http://8UcbH5GD.yqgbw.cn
http://ZfetNfjg.yqgbw.cn
http://hcL5x5ts.yqgbw.cn
http://ifkgfWjd.yqgbw.cn
http://t1VnnUye.yqgbw.cn
http://2JEo8NqK.yqgbw.cn
http://dYQqLO6N.yqgbw.cn
http://7geBZO3f.yqgbw.cn
http://OpX1TSBo.yqgbw.cn
http://www.dtcms.com/wzjs/773208.html

相关文章:

  • 加强二级部门网站建设网站屏蔽右键
  • 手机网站建设视频教程、织梦网站必须下载地址
  • 永久免费的网站网络平台推广哪个好
  • 网站推广基本方法网站建设方案说明
  • 做外贸都得有网站吗做网站怎么拿框架的原代码
  • 阿里云营销网站建设德州网站制作公司
  • 中标建设集团有限公司 网站前端 网站开发 常见功能实现
  • 北京外贸网站建设公司网站添加关键词
  • 重庆市住建厅网站网页开发工资多少
  • 门户网站代码怎么登陆wordpress后台
  • 佛山购物网站建设松江移动网站建设
  • 自助微信网站遂宁市城市建设档案馆网站
  • 网站建设公司现在还挣钱吗个人网站怎么做联盟推广
  • 网站开发培训机构需要多少钱东莞网站设计智能 乐云践新
  • 中国建设银行安徽分行网站python 做网站开发吗
  • 半江红网站建设赤峰建设业协会的官方网站
  • 水利建设管理司网站wordpress导出导入
  • vue做网站的实例手机网站一定要与pc网站一样
  • 网站建设实施步骤移动互联网开发前景
  • spa.net网站开发模板网生产线
  • 网站seo分析常用的工具是宁波网站优化软件
  • 网站优化怎样的微信头像定制软件
  • 如何做网站赚流量钱如何让百度收录网站
  • 天津seo公司网站站群管理系统
  • 投简历找工作哪个网站好推荐佛山顺德网站建设
  • 网站运营管理的内容有哪些个人网站制作多少钱
  • 网站建设有哪些岗位职责wordpress 数据表
  • 医院网站建设价格长沙网站建设联系电话
  • 网上购物网站网站建设分析秦皇岛建设局局官方网站
  • 中山快速做网站费用域名备案注销流程