基础协程概念
协程是可暂停计算的一个实例。
协程在概念上与线程相似,但协程并不约束于任一线程(可以在不同的线程中挂起和唤醒)
第一份协程代码
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