我们将通过实例来逐步了解kotlin协程,协程基础性东西看官网文档最好了
Coroutines guide | Kotlin (kotlinlang.org)
假设你现在对协程有了一定了解,我们来看这个实例,你能正确说出输出顺序吗? 为什么?
//你能说出下面代码输出顺序 代表你对协程有了一丢丢了解了,注意不能错一点,错一点就代表对协程了解为0
@Test
fun testLaunch(){
runBlocking {
launch {
println("launch1 started")
delay(3000)
println("launch1 ended")
}
launch {
println("launch2 started")
delay(2000)
println("launch2 ended")
}
println("go go")
}
}
那么先来看答案,然后在解析它
go go
launch1 started
launch2 started
launch2 ended
launch1 ended
我们先逐行看看上面的代码干了什么
@Test//测试注解而已没什么可说的, 不习惯用main函数去测试这个代码也一样的
fun testLaunch(){//没啥说的
runBlocking {//runBlocking是一个协程构建器,它会启动一个阻塞线程的协程,但也是协程,coroutine#main
launch {//lauch也是协程构建器,启动了一个新协程,我们称它为coroutine#1, 它是coroutine#main的子协程
println("launch1 started")//打印信息
delay(3000)//暂停3000ms,也说是挂起
println("launch1 ended")//打印信息
}
launch {//同上,只是顺序在coroutine#1的后面 我们称其coroutine#2
println("launch2 started")//打印信息
delay(2000)//暂停2000ms,也说是挂起
println("launch2 ended")//打印信息
}
println("go go")//打印信息
}
}
所有的行都加了注释,那么我们看到一共有3个协程 #main, #1, #2。那么显然#main是最先执行的协程, 它主体上干了3件事,第一件事 创建#1, 然后创建#2,最后打印 "gogo", 你可能会说:"那为啥先输出gogo 而不是launch1 started"? 第一件事不是创建#1吗, 是的第一件事是创建#1,但协程是需要唤醒才能执行的,创建#1时,主协程#main还没有到达挂起点,#1只能是挂起(suspend)状态,它在等待调度或者说在等待挂起点。 那么#2也是一样的道理,这样的话#main最后会执行println("go go"),也就是我们先看到"go go"输出的原因了, 此时主协程没事情做了,这样就自然到达了它的挂起点,注意#main此时并没有退出只是挂起了, 这时根据先后顺序协程#1发现了这个挂起点,从而得到了调度唤醒, 它首先执行了 println("launch1 started"), 这显而易见。然后执行“delay(3000)”,这个delay就是挂起的意思,此时#1挂起, #2得到唤醒 执行" println("launch2 started")",然后#2也挂起delay(2000), 那之后其实是显而易见的 #2挂起的时间短 所以launch2 ended得以先输出 #2完成使命彻底消亡,最后是launch1 ended,#1消亡,此时#main发现所有子协程已经 退出,它也功成身退,彻底退出,至此程序得以结束。
好了 这个就是协程最简单的实例分析了,下回见
网友评论