5

Kotlin Coroutines Notes (I)

 2 years ago
source link: https://scottyeung.top/2021/kotlin-coroutines-notes-1/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
 2021.12.15  2022.3.3  Posts  29

对于 Kotlin 官方文档当中 coroutines 部分的内容的学习 (翻译)

在 Kotlin 当中,协程(coroutines)通过库 kotlinx.coroutines 来提供,相较于其它语言的协程实现,Kotlin 选择的方式更为没有侵入性,其所使用的 asyncawait 等只是库提供的函数,而非语言自身的关键字,因而能够有着更好的兼容性。另外 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

fun main() = runBlocking { // this: CoroutineScope
    launch { // launch a new coroutine and continue
        delay(1000L) //  delay for 1 second (default time unit is ms)
        println("World!") // print after delay
    }
    println("Hello") // main coroutine continues while a previous one is delayed
}
  • launch: coroutine builder,用于开启一个新的协程(coroutine)来执行代码块,开启协程代码与其余代码同时独立地执行。
  • delay: 暂停协程一定时间后再恢复执行,这里的暂停并不会阻塞底层
  • runBlocking: 开启一个 coroutine scope, 并阻塞至其中所有协程执行完

只有在 coroutine scope 当中才能够通过 launch 开启新的协程,凭借此限制 Kotlin 可以实现结构化的并发(structured concurrency),保证了 CoroutineScope 必然会等待其中所有子协程完成才完成。

控制协程与结果获取

  • 通过 launch 开启一个新协程后同时会返回一个 Job 的对象,跟 C# 当中的 Task 比较类似,可以通过改对象来对协程任务进行控制(暂停或取消)
  • 通过 async 可以获取一个 Deferred 对象,类似于 FuturePromise 对象,存储了计算过程,但延迟了获取结果。it promises the result sometime in the future.

两者使用的区别主要是开启的协程是否有返回值。Deferred 类型为继承 Job 的泛型类型

  • Deferred 对象可以通过 await 方法阻塞等待结果返回
  • 对于多个 Deferred 对象可以通过对其所在的 List 当中调用 awaitAll 阻塞等待所有任务完成返回

Channel

Kotlin 当中使用 Channel 来进行协程间的通信,就概念上来讲,其实跟 Go 当中的 channel 是一致的:不同 coroutines 通过往 channel 当中传输与接收数据,进行通信。不过 Kotlin 当中 Channel 为接口,使用的时候也是想普通的对象初始化与函数调用,通过 sendreceive 方法进行数据传输,与 Go 当中使用 <- 等作为语言特性的使用方式不同。

Kotlin 当中的协程类型有 4 种

  • 无限制 channel:channel 当中存储数量无限制
  • 带缓冲 channel:限制 channel 当中可以存储的数量,当 send 的时候 channel 当中元素数量超过缓冲数量限制则会阻塞
  • Rendezvous channel:相当于缓冲数量为 0 的缓冲 channel,每次 send 后都必须要等有人 receive 才能停止阻塞
  • Conflated channel:缓冲容量为 1,但每次 send 并不会阻塞,而是会把里面有的元素给覆盖掉
val rendezvousChannel = Channel<String>()
val bufferedChannel = Channel<String>(10)
val conflatedChannel = Channel<String>(CONFLATED)
val unlimitedChannel = Channel<String>(UNLIMITED)

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK