抽丝剥茧聊Kotlin协程之协程启动原理

简介: 抽丝剥茧聊Kotlin协程之协程启动原理

1. 前言



本文主要介绍协程的启动原理,如果没有协程实战经验或者没有Debug过协程的源码,看起来可能会有点费劲,但是如果将来有机会学习协程的源码,那么这篇文章可能会对你有一定的帮助。文章主要是讲解协程启动的流程,简便起见,该过程中涉及到的其它比较重要协程知识点可能只会简单提到,本文不会深入去讲解,后续有空会对他们单独成文。


2. 简单的例子



首先 我们来看一个简单的例子,在主线程中开启一个协程,打印“Hello Coroutines”。通过这个简单的例子讲解协程是如何启动起来的。


image.png

接着我们将startCoroutines方法反编译成Java文件


image.png

我们看到Kotlin代码中的Lambda表达式变成了Java中的Function2对象,而它对应的具体类是SuspendLambda。 我们注意到它实现了三个方法:


  1. Object invokeSuspend(Object var1)
  2. Continuation create(Object value,Continuation completion)
  3. Object invoke(Object var1,Object var2)


image.png

image.png

image.png

大家仔细看就会发现,invokeSuspend和create方法定义在BaseContinuationImpl中,invoke方法定义Function2中。而SuspendLambda继承了ContinuationImpl同时又实现了SuspendFunction接口。


在Kotlin中,方法也是对象,一个参数的方法对应的类是Function1,以此类推两个参数方法对应的是Function2。

行文至此,有很多新东西,suspend、Continuation、CoroutineScope、CoroutineContext,但是本文不会讲解,接着往下看协程启动过程吧。


3. 启动过程


3.1 CoroutineScope.launch


image.png

该方法功能如下:


  1. 为新协程创建一个新的CoroutineContext
  2. 本文Case创建StandaloneCoroutine
  3. 调用coroutine.start方法启动协程

image.png

该方法功能如下:


  1. 调用initParentJob方法,与父Job建立关联,当调用cancel方法或者子Job有异常时,可以将取消或者异常事件往上传播(本文暂且忽略,简单了解就好了
  2. 调用start(block, receiver, this),该方法超级有迷惑性,它真正调用的是CoroutineStart的invoke方法。


3.2 CoroutineStart.invoke


image.png

本案例中执行DEFAULT分支


3.3 (suspend(R)->T).startCoroutineCancellable

image.png



最终是通过suspend方法的startCoroutineCancellable方法来启动协程的,本文对应的是lambda,前文我们讲过它对应的是SuspendLambda


{
  println("Hello Coroutines")
}


该方法包含了几个重要方法的调用:


  1. (suspend R.()->T).createCoroutineUnintercepted
  2. Continuation.intercepted()
  3. Continuation.resumeCancellableWith


3.4 (suspend R.() -> T).createCoroutineUnintercepted


image.png

当前的this是启动协程的闭包,前面我们通过反编译startCoroutines方法,发现闭包实现了create方法,此处调用的正是反编译后生成的create方法


image.png参数completion对应的是协程StandaloneCoroutine,此处生成的Function2对象也是SuspendLambda对象


3.5 Continuation.intercepted()


image.png

该方法的主要作用就是生成DispatchedContinuation。它由CoroutineDispatcher和Continuation两部分组成。Dispatcher决定在Continuation在哪个线程中执行,本文是在主线程


3.6 Continuation.resumeCancellableWith


image.png

3.7 MainScope

image.png

image.png

Dispatchers.Main 最终由

kotlinx.coroutines.android.AndroidDispatcherFactory创建


3.8 AndroidDispatcherFactory

image.png

最终通过Handler.post方法把DispatchedContinuation放入主线程消息队列


3.9 DispatchedTask.run


Android主线程调度,最终会调用到DispatchedTask.run方法中,通过continuation.resume方法执行协程体。


image.png


3.10 BaseContinuationImpl.resumeWith


ContinuationImpl.kt

image.png

该方法循环调用Continuation的invokeSuspend方法,直到当前completion是协程本身会跳出循环。


真正执行打印“Hello Coroutines”


image.png

3.11 AbstractCoroutine.resumeWith


协程执行完成

image.png

表示协程执行结束,它可能需要等待子协程结束,结束后需要告知父协程


4. 总结



协程的前置知识点太多了,一篇文章无法解释清楚,有疑问可以在评论区提出。本文主要是讲解了Dispatchers.Main启动协程的过程。Dispatchers.Default启动协程的过程与它又完全不同。

相关文章
|
2月前
|
存储 Linux 调度
协程(coroutine)的原理和使用
协程(coroutine)的原理和使用
|
8天前
|
调度 Python
揭秘Python并发编程核心:深入理解协程与异步函数的工作原理
在Python异步编程领域,协程与异步函数成为处理并发任务的关键工具。协程(微线程)比操作系统线程更轻量级,通过`async def`定义并在遇到`await`表达式时暂停执行。异步函数利用`await`实现任务间的切换。事件循环作为异步编程的核心,负责调度任务;`asyncio`库提供了事件循环的管理。Future对象则优雅地处理异步结果。掌握这些概念,可使代码更高效、简洁且易于维护。
11 1
|
2月前
|
调度 开发者 UED
Kotlin 中的协程是什么?
【8月更文挑战第31天】
56 0
|
3月前
|
SQL 安全 Java
Android经典面试题之Kotlin中object关键字实现的是什么类型的单例模式?原理是什么?怎么实现双重检验锁单例模式?
Kotlin 单例模式概览 在 Kotlin 中,`object` 关键字轻松实现单例,提供线程安全的“饿汉式”单例。例如: 要延迟初始化,可使用 `companion object` 和 `lazy` 委托: 对于参数化的线程安全单例,结合 `@Volatile` 和 `synchronized`
43 6
|
3月前
|
调度 Python
揭秘Python并发编程核心:深入理解协程与异步函数的工作原理
【7月更文挑战第15天】Python异步编程借助协程和async/await提升并发性能,减少资源消耗。协程(async def)轻量级、用户态,便于控制。事件循环,如`asyncio.get_event_loop()`,调度任务执行。异步函数内的await关键词用于协程间切换。回调和Future对象简化异步结果处理。理解这些概念能写出高效、易维护的异步代码。
45 2
|
4月前
|
存储 Java 调度
Android面试题之Kotlin 协程的挂起、执行和恢复过程
了解Kotlin协程的挂起、执行和恢复机制。挂起时,状态和上下文(局部变量、调用栈、调度器等)被保存;挂起点通过`Continuation`对象处理,释放线程控制权。当恢复条件满足,调度器重新分配线程,调用`resumeWith`恢复执行。关注公众号“AntDream”获取更多并发知识。
79 2
|
5月前
|
移动开发 Android开发 开发者
构建高效Android应用:Kotlin与协程的完美融合
【5月更文挑战第25天】 在移动开发的世界中,性能和响应性是衡量应用质量的关键指标。随着Kotlin的流行和协程的引入,Android开发者现在有了更强大的工具来提升应用的性能和用户体验。本文深入探讨了Kotlin语言如何与协程相结合,为Android应用开发带来异步处理能力的同时,保持代码的简洁性和可读性。我们将通过实际案例分析,展示如何在Android项目中实现协程,以及它们如何帮助开发者更有效地管理后台任务和用户界面的流畅交互。
|
5月前
|
移动开发 数据库 Android开发
构建高效Android应用:探究Kotlin的协程优势
【5月更文挑战第22天】随着移动开发技术的不断进步,Android平台的性能优化已经成为开发者关注的焦点。在众多提升应用性能的手段中,Kotlin语言提供的协程概念因其轻量级线程管理和异步编程能力而受到广泛关注。本文将深入探讨Kotlin协程在Android开发中的应用,以及它如何帮助开发者构建出更高效、响应更快的应用,同时保持代码的简洁性和可读性。
|
5月前
|
移动开发 Android开发 开发者
构建高效安卓应用:Kotlin 协程的实践指南
【5月更文挑战第18天】 随着移动开发技术的不断进步,安卓平台亟需一种高效的异步编程解决方案来应对日益复杂的应用需求。Kotlin 协程作为一种新兴的轻量级线程管理机制,以其简洁的语法和强大的功能,成为解决这一问题的关键。本文将深入探讨Kotlin协程在安卓开发中的实际应用,从基本概念到高级技巧,为开发者提供一份全面的实践指南,旨在帮助读者构建更加高效、稳定的安卓应用。
|
5月前
|
移动开发 安全 Android开发
构建高效Android应用:Kotlin与协程的完美结合
【5月更文挑战第17天】 在移动开发领域,性能优化和流畅的用户体验是关键。对于Android平台而言,Kotlin语言凭借其简洁性和功能安全性成为开发的首选。与此同时,协程作为一种新的并发处理方式,在简化异步编程方面展现出巨大潜力。本文将深入探讨如何通过Kotlin语言以及协程技术,提升Android应用的性能和响应能力,并确保用户界面的流畅性。
下一篇
无影云桌面