对于 Kotlin 官方文档当中 coroutines 部分的内容的学习
(翻译)
在 Kotlin 当中,协程(coroutines)通过库 kotlinx.coroutines
来提供,相较于其它语言的协程实现,Kotlin 选择的方式更为没有侵入性,其所使用的 async
和 await
等只是库提供的函数,而非语言自身的关键字,因而能够有着更好的兼容性。另外 Kotlin 当中提供的挂起函数 (suspending function)的概念,能为 Kotlin 当中 coroutines 提供比 Java 和 Javascript 当中的 future and promise 更加直观,安全,不易错的抽象
suspend function
A suspending function is simply a function that can be paused and resumed at a later time. They can execute a long running operation and wait for it to complete without blocking.
所谓的挂起其实可以理解成这个函数将不会阻塞当前线程,调用一个函数后就丢到后面自己执行
A suspend function can't be called everywhere. It should only be called from a coroutine or another suspend function
Basic
Kotlin 当中 coroutine 的概念其实跟 Go 当中的比较类似,可以当作是一个轻量级的线程。不过 coroutine 并不绑定于某个具体的线程,其也可以在一个线程当中挂起,在另一个线程当中继续执行,所以可以理解为在基本线程上面的一层抽象的“轻量线程”。
当然其实初期我们也不太需要理解其具体如何实现,先学会怎么用更实际
example
|
|
launch
: coroutine builder,用于开启一个新的协程(coroutine)来执行代码块,开启协程代码与其余代码同时独立地执行。delay
: 暂停协程一定时间后再恢复执行,这里的暂停并不会阻塞底层runBlocking
: 开启一个 coroutine scope, 并阻塞至其中所有协程执行完
只有在 coroutine scope 当中才能够通过 launch 开启新的协程,凭借此限制 Kotlin 可以实现结构化的并发(structured concurrency),保证了 CoroutineScope 必然会等待其中所有子协程完成才完成。
控制协程与结果获取
- 通过
launch
开启一个新协程后同时会返回一个 Job 的对象,跟 C# 当中的 Task 比较类似,可以通过改对象来对协程任务进行控制(暂停或取消) - 通过
async
可以获取一个Deferred
对象,类似于Future
和Promise
对象,存储了计算过程,但延迟了获取结果。it promises the result sometime in the future.
两者使用的区别主要是开启的协程是否有返回值。Deferred
类型为继承 Job
的泛型类型
结果获取
Deferred
对象可以通过 await 方法阻塞等待结果返回- 对于多个
Deferred
对象可以通过对其所在的List
当中调用awaitAll
阻塞等待所有任务完成返回
Channel
Kotlin 当中使用 Channel 来进行协程间的通信,就概念上来讲,其实跟 Go 当中的 channel 是一致的:不同 coroutines 通过往 channel 当中传输与接收数据,进行通信。不过 Kotlin 当中 Channel 为接口,使用的时候也是想普通的对象初始化与函数调用,通过 send
和 receive
方法进行数据传输,与 Go 当中使用 <-
等作为语言特性的使用方式不同。
Kotlin 当中的协程类型有 4 种
- 无限制 channel:channel 当中存储数量无限制
- 带缓冲 channel:限制 channel 当中可以存储的数量,当
send
的时候 channel 当中元素数量超过缓冲数量限制则会阻塞 - Rendezvous channel:相当于缓冲数量为 0 的缓冲 channel,每次
send
后都必须要等有人receive
才能停止阻塞 - Conflated channel:缓冲容量为 1,但每次
send
并不会阻塞,而是会把里面有的元素给覆盖掉
|
|