基础协程概念
协程是可暂停计算的一个实例。
协程在概念上与线程相似,但协程并不约束于任一线程(可以在不同的线程中挂起和唤醒)
第一份协程代码
import kotlinx.coroutines.*
fun main() = runBlocking { // this: CoroutineScope
launch { // launch a new coroutine and continue
delay(1000L) // non-blocking 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
}
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
launch 是协程的创建器(builder) 可以启动一个独立工作的协程
delay 是一种特殊的suspend函数 可以挂起协程但不阻塞当前线程
runBlocking 也是协程的builder 用于连接非协程域和协程域 类型为CoroutineScope
runBlocking 构建一个阻塞当前线程的协程域
结构化并发
协程遵循结构化并发的原则 即新的协程只能在一个特定的
CoroutineScope中启动
提取函数
如何将launch块中的语句提取成一个函数?
import kotlinx.coroutines.*
fun main() = runBlocking { // this: CoroutineScope
launch { doWorld() }
println("Hello")
}
// this is your first suspending function
suspend fun doWorld() {
delay(1000L)
println("World!")
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
结合上例,可以看出提取函数的特点 需要在协程中执行的函数 需要添加 suspend 修饰符
在IDE中 可以通过
Extract funcion功能提取函数
suspend 函数跟常规函数类似 只是它们还能调用 suspend 函数(suspend函数可以相互间调用)
Scope builder
可以使用 coroutineScope 声明自己的协程域
coroutineScope 会创建一个协程域 当域内所有协程结束时它才会结束
coroutineScope和runBlocking的主要区别是 后者(常规函数)会阻塞当前线程 而前者(suspend函数)不会 但会挂起外部协程
可以在任何suspend函数中使用coroutineScope 可以将上例改为这样
fun main() = runBlocking {
doWorld()
}
suspend fun doWorld() = coroutineScope { // this: CoroutineScope
launch {
delay(1000L)
println("World!")
}
println("Hello")
}
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
并发
coroutineScope 可以在任何 suspend 函数中用来执行多并发操作 例如下例中同时运行两个协程
// Concurrently executes both sections
suspend fun doWorld() = coroutineScope { // this: CoroutineScope
launch {
delay(2000L)
println("World 2")
}
launch {
delay(1000L)
println("World 1")
}
println("Hello")
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
这两个协程会同时执行
显式 job
一个 launch 协程builder 返回一个 Job 对象
该对象可以处理这个已启动的协程 也可以用于显式等待 join
val job = launch { // launch a new coroutine and keep a reference to its Job
delay(1000L)
println("World!")
}
println("Hello")
job.join() // wait until child coroutine completes
println("Done")
// 输出:
// Hello
// World!
// Done
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11