问题
首先还是先抛出一系列的问题,大家搞清楚这些问题后学习 Kotlin 协程可能会轻松一点:
1、什么是并发?什么是并行?
2、什么是多任务?什么是协作式多任务?什么是抢占式多任务?
3、什么是同步?什么是异步?
4、什么是非阻塞式?什么是阻塞式?
5、什么是挂起?
6、什么是非阻塞式挂起?
7、什么是协程?
8、什么是 Kotlin 协程?
9、Kotlin 协程有什么用?
1、什么是并发?什么是并行?
1)、并发就是同一时刻只有一条指令在执行,但是因为 CPU 时间片非常的小,多个指令间能够快速的切换,使得我们看起来拥有同时执行的效果,存在于单核或多核 CPU 系统中
2)、并行就是同一时刻有多条指令同时在执行,存在于多核 CPU 系统中
举个生活中人吃馒头的例子:一个人买了 3 个馒头,那么他同一时刻只能在吃一个馒头,这是并发。而 3 个人每人买了一个馒头,那么同一时刻他们能同时吃馒头,这是并行。并发和并行的区别在于同一时刻是否在同时进行
2、什么是多任务?什么是协作式多任务?什么是抢占式多任务?
1)、多任务就是操作系统能够同时处理多个任务,例如我可以使用笔记本电脑打开 AndroidStudio 和网易云音乐,一边撸码一边听歌
2)、协作式多任务就是一个任务得到了 CPU 时间,除非它自己放弃使用 CPU ,否则将完全霸占 CPU ,所以任务之间需要协作,使用一段时间的 CPU 后,放弃使用,其它的任务也如此,才能保证系统的正常运行。一般出现在早期的操作系统中,如 Windows 3.1
3)、抢占式多任务就是由操作系统来分配每个任务的 CPU 使用时间,在一个任务使用一段时间 CPU 后,操作系统会剥夺当前任务的 CPU 使用权,把它排在询问队列的最后,再去询问下一个任务。一般出现在现在使用的操作系统,如 Window 95及之后的 Windows 版本
协作式多任务和抢占式多任务区别:在协作式多任务中,如果一个任务死锁,则系统也会死锁。而抢占式多任务中,如果一个任务死锁,系统仍能正常运行
3、什么是同步?什么是异步?
计算机领域中的同步和异步和我们平时生活中的同步和异步是不一样的,这就让很多人难以理解
1)、计算机领域中的同步就是当调用者发送一个调用指令,需等待该指令执行完,在继续往下执行,是一种串行的处理方式
2)、计算机领域中的异步就是当调用者发送一个调用指令,无需等待该指令执行完,继续往下执行,是一种并行的处理方式
4、什么是阻塞?什么是非阻塞?
阻塞很简单,就是字面意思,在 Android 中的体现,其实就是阻塞了主线程的运行,那么非阻塞就是没有卡住主线程的运行
5、什么是挂起?
挂起就是保存当前状态,等待恢复执行,在 Android 中的体现,挂起就是不影响主线程的工作,更贴切的说法可以理解为切换到了一个指定的线程,
6、什么是非阻塞式挂起?
通过上面概念的解释,非阻塞式挂起就是不会卡住主线程且将程序切换到另外一个指定的线程去执行
7、什么是协程?
协程,英文名 Coroutine,源自 Simula 和 Modula-2 语言,它是一种协作式多任务实现,是一种编程思想,并不局限于特定的语言。协程设计的初衷是为了解决并发问题,让协作式多任务实现起来更加方便
8、什么是 Kotlin 协程?
Kotlin 协程简单来说是一套线程操作框架,详细点说它就是一套基于线程而实现的一套更上层的工具 API,类似于 Java 的线程池,你可以理解 Kotlin 新造了一些概念用来帮助你更好地使用这些 API,仅此而已
9、Kotlin 协程有什么用?
1)、Kotlin 协程可以用看起来同步的方式写出异步的代码,帮你优雅的处理回调地狱
清楚了上面这些问题后,我们接着往下看
一、Kotlin 协程生态和依赖库
Kotlin 并没有把协程纳入标准库中,而是以依赖库的形式提供的,这是一张 Kotlin 协程的生态图:
image-20210414204413591
从上图我们可以很清晰的看到,Kotlin 标准库和协程依赖库所提供的东西,在我们创建一个 Kotlin 项目的时候,默认会导入标准库的依赖,因此这里添加如下协程依赖库就可以了,最新协程依赖库版本可以点击传送门查看:
//协程核心库
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.3'
//这个库在 Android 项目中才会用到
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.3'
二、使用 GlobalScope.launch 函数创建你的第一个协程
- GlobalScope.launch 函数可以创建一个协程作用域,这样传递给 launch 函数的代码块就是在协程中运行了
- GlobalScope.launch 函数创建的是一个顶级协程,当应用程序运行结束时也会跟着一起结束
- GlobalScope.launch 函数创建的协程和线程有点像,因为线程没有顶级这一说,所以永远都是顶级的
fun main() {
GlobalScope.launch {
println("codes run in coroutine scope")
}
}
上面这段简短的代码就是开启了一个协程,很简单吧,一行代码就实现了,协程也不过如此啊😂。实际下面这段代码背后包含着成吨的知识点:
1、协程作用域
2、协程作用域的扩展函数
3、协程上下文
4、协程启动模式
可能大家会有点疑惑,区区一行代码,怎么可能会涉及这么多东西?不信我们在点击 launch 函数看下它的源码:
// launch 函数源码
public fun CoroutineScope.launch(
context: CoroutineContext = EmptyCoroutineContext,
start: CoroutineStart = CoroutineStart.DEFAULT,
block: suspend CoroutineScope.() -> Unit
): Job {
//...
}
可以看到,launch 函数是 CoroutineScope 即协程作用域的一个扩展函数,它里面有三个参数:第一个参数: CoroutineContext 即协程上下文,有默认值。第二个参数: CoroutineStart 即协程启动模式,有默认值。第三个参数:函数类型参数