和其他语言不同,Kotlin 只在标准库中提供最小化的低级 API 来工具化协程。和其他语言不同,async 和 await 在 Kotlin 中不是关键字,它们甚至都没出现在标准库中。Kotlin 的 suspending 函数概念提供了更加安全的、不易错的抽象用于异步操作,而不是 future 和 promise。
Jetbrains 开发的 kotlinx.coroutines 是一个用于丰富的协程库。它提供了很多用起来更加方便的高级携程 API,比如 launch、async 等。这里主要介绍这个库。
使用
gradle TODO:
maven TODO:
协程基础
在线程执行过程中开启一个协程
import kotlinx.coroutines.*fun main() {GlobalScope.launch { // 开启一个新协程并继续delay(1000L) // 非阻塞延迟 1sprintln("World!") // 延迟后打印 world}println("Hello,") // 在协程延迟时,主线程正常执行Thread.sleep(2000L) // 主线程 sleep 2s 以确保 JVM 不立刻结束}
上面的代码,先立刻输出 Hello,1秒后输出 world,2秒后结束。
如果把第 9 行注释掉,上面的代码在输出 Hello 之后立刻就结束了。
协程是轻量级线程。上面的代码在 GlobalScope 中启动了一个新的协程,这意味着新协程的生存时间仅受限于整个应用程序的生存时间。
以阻塞方式执行协程
使用 runBlocking
import kotlinx.coroutines.*fun main() {GlobalScope.launch { // 开启一个新协程并继续delay(1000L) // 非阻塞延迟 1sprintln("World!") // 延迟后打印 world}println("Hello,") // 在协程延迟时,主线程正常执行runBlocking {delay(2000L)}}
runBlocking 包装一个协程的执行为“同步操作”。执行 runBlocking 的线程会被阻塞,直到协程结束为止。
- runBlocking 时,主线程的状态是什么? TODO:
- 哪个线程在执行 runBlocking?TODO:
另外,runBlocking 可以返回一个结果:
val v = runBlocking {delay(2000L)return@runBlocking 2234}println(v) // 输出 2234
在线程中等待 Job 执行完成
Global.launch 返回一个 Job。我们可以使用 Job api 来主动等任务完成:
val job = GlobalScope.launch {delay(1000L)println("World!")}println("Hello,")job.join() // 等待协程完成
