关注我的公众号 “安安安安卓” 学习更多知识
关于协程分了四部分来写
默认顺序调用
顺序调用两个 suspend 函数的时候,两个函数是串行执行的
- 代码
fun main() = runBlocking {
val startStamp = System.currentTimeMillis()
a()
b()
log("代码运行总时长:${System.currentTimeMillis()-startStamp}")
}
suspend fun a(){
delay(2000)
log(A)
}
suspend fun b(){
delay(3000)
log(B)
}
复制代码
- 日志
日志: A
日志: B
日志: 代码运行总时长:5015
复制代码
- 结论
协程里面两个并行的 suspend 函数会串行执行,呼应开头的结论
使用 async 实现并发
上面例子中我们使用两个 suspend 函数串行执行函数,如果使用两个 async 执行 suspend 方法的话可以实现并发执行的效果。
aysnc 返回一个 Deferred 对象,Deferred 是一个轻量级阻塞式对象,可以调用 Deferred.await()延迟获取返回结果
Deferred 也是一个 Job,所以也可以取消操作
- 代码
fun main() = runBlocking {
val startStamp = System.currentTimeMillis()
val deferredA=async {
a()
}
val deferredB=async {
b()
}
deferredA.await()
deferredB.await()
log("执行总时长:${System.currentTimeMillis()-startStamp}")
}
suspend fun a(){
delay(2000)
log(A)
}
suspend fun b(){
delay(3000)
log(B)
}
复制代码
- 日志
日志: A
日志: B
日志: 执行总时长:3022
复制代码
- 结论
上一节中代码执行总耗时 5105,本节总耗时 3022。这说明两个 async 是并发执行的
惰性启动的 async
async 可以通过将 start 参数设置为 CoroutineStart.LAZY 而变为惰性的。 在这个模式下,只有结果通过 await 获取的时候协程才会启动,或者在 Job 的 start 函数调用的时候
- 代码
fun main() = runBlocking {
val deferred = async (start = CoroutineStart.LAZY){
delay(2000)
log(A)
"async执行完成"
}
log(deferred.await())
}
复制代码
- 日志
日志: A
日志: async执行完成
复制代码
-
结论
必须调用 await 或 start 才能启动,
使用 async 的结构性并发
协程体作用域中并发的多个 async,有一个发生异常其它的 async 也会被取消
- 代码
fun main() = runBlocking {
async {
log("吃饭aa,别bb")
delay(100)
throw IllegalArgumentException("打你一嘴巴子,你再bb")
}
async {
log("就bb,咋地")
delay(300)
log("bb完了")
}
log("程序结束")
}
复制代码
- 日志
日志: 程序结束
日志: 吃饭aa,别bb
日志: 就bb,咋地
Exception in thread "main" java.lang.IllegalArgumentException: 打你一嘴巴子,你再bb
at SuspendMethodKt$main$1$1.invokeSuspend(SuspendMethod.kt:55)
复制代码
-
记录
当第一个 async 抛出异常后,第二个 async 后面 “bb 完了”的日志没有打印,说了第二个 async 也同步被取消了。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END