协程总纲:从底层到高层

49 阅读3分钟

0) 本体与大图

  • 协程 = 可挂起/可恢复的函数,编译为CPS + 无栈状态机:局部变量进堆对象,label 记录继续点。

  • 核心三要素:Continuation(续延/状态机入口)、Dispatcher(在哪个线程恢复)、Job(生命周期与取消)。

1) 挂起与恢复(机制)

  • 编译产物:suspend fun f(...) → Object f(..., Continuation)。

  • 到挂起点:保存局部 & label → 返回 COROUTINE_SUSPENDED

  • 恢复:外界在合适线程调用 resumeWith(Result),状态机按 label 继续。

2) 调度(在哪儿继续跑)

  • 拦截器:ContinuationInterceptor 拦截并包装为 DispatchedContinuation

  • 判定:isDispatchNeeded(context) 为 false → inline 恢复;否则 dispatch 投递到 Dispatcher(如 Main/IO/Default)。

  • 常用语义:Main.immediate(主线程可直跑)、Unconfined(首段当前线程、后续跟随唤醒源)。

3) 取消与 Job 状态机(怎么停)

  • 协作式取消:只在挂起点或显式检查(isActive/ensureActive/yield)生效。

  • 状态:New(LAZY) → Active → Completing → Completed;遇异常/取消进入 Cancelling → Cancelled。

  • 传播:coroutineScope 一死全死;supervisorScope/SupervisorJob 子死不传染

  • 清理:finally + withContext(NonCancellable) 保证资源释放。

4) 挂起桥(把回调变 suspend)

  • suspendCoroutine:不可取消桥;适合短平快、无清理需求。

  • suspendCancellableCoroutine:可取消桥;invokeOnCancellation{…} 做撤销/解绑;并用 tryResume*/completeResume 只恢复一次

5) 异常学(抛到哪、什么时候抛)

  • launch:异常立即上抛;根协程走 CoroutineExceptionHandler。

  • async:异常封进 Deferred,在 await() 抛;但在 coroutineScope 中仍会立刻取消父与兄弟

  • 首错优先:同时失败时以首个异常为主,其余挂 suppressed

6) Flow 内部与“融合”

  • 默认单协程直通:map/filter/transform/... 彼此内联融合,无额外队列/线程。

  • 打断融合 = 建边界:buffer/conflate/collectLatest/flowOn/flatMap*/zip/combine/shareIn/stateIn → 额外协程 + Channel。

  • StateFlow:**自带“最新值 + equals 去重”合流(conflate)**语义,故 distinctUntilChanged 对其无效(已内置)。

  • 位置建议:flowOn 靠近源头;buffer 放在瓶颈前;边界能少不多。

7) 背压与多播/单播选型

  • 拉链式背压(挂起背压) :Flow/Channel 的 emit/send 在下游慢时会挂起。

  • 细粒度控制

    • 单播 + 可控背压 ⇒ Channel(RENDEZVOUS 最强、BUFFERED 吸突发、CONFLATED/DROP_OLDEST 只要最新)。

    • 串行改写可变状态 ⇒ Actor(Channel + 单协程事件循环)

    • 广播/多订阅 ⇒ SharedFlow/StateFlow无挂起背压,靠缓冲/重放而非阻塞)。

8) 结果并发与容错套路

  • 并发取结果:coroutineScope { val a = async{…}; val b = async{…}; a.await() to b.await() }。

  • 容错并发:supervisorScope + runCatching 或 await() 后自处理。

  • LAZY 并发:多个 async(LAZY) 先 start() 再 await(),避免串行。

9) 调试与排错要点

  • 看异常:Deferred.getCompletionExceptionOrNull();Job.invokeOnCompletion{ cause }。

  • 看边界:遇到线程漂移/吞吐抖动,先找 flowOn/buffer/flatMap*。

  • 看取消卡顿:CPU 循环加 ensureActive()/yield();IO 用挂起 API。

  • 看资源泄漏:回调桥必须 invokeOnCancellation 对称清理,Actor 里致命错后 close(cause)。

10) 速查表(拍脑袋有底)

  • 机制:Continuation + label;resumeWith;COROUTINE_SUSPENDED。
  • 调度:ContinuationInterceptor → DispatchedContinuation → Dispatcher。
  • 取消:协作式;coroutineScope 连坐,supervisorScope 不连坐。
  • 桥接:suspend(Cancellable)Coroutine;tryResume/completeResume 防双写。
  • 异常:launch 立即;async await 才抛;根异常走 CoroutineExceptionHandler。
  • 融合:轻运算符内联;flowOn/buffer/flatMap*/latest/zip/combine 打断。
  • 背压/多播:Flow 背压=挂起;单播/强背压→Channel/Actor多播→SharedFlow/StateFlow