协程搬运工-组合挂起函数

关注我的公众号 “安安安安卓” 学习更多知识

关于协程分了四部分来写

协程搬运工-上下文和调度器

协程搬运工-组合挂起函数

协程搬运工-取消与超时

协程搬运工-基础

默认顺序调用

顺序调用两个 suspend 函数的时候,两个函数是串行执行的

  1. 代码
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)
}
复制代码
  1. 日志
日志:  A
日志:  B
日志:  代码运行总时长:5015
复制代码
  1. 结论
    协程里面两个并行的 suspend 函数会串行执行,呼应开头的结论

使用 async 实现并发

上面例子中我们使用两个 suspend 函数串行执行函数,如果使用两个 async 执行 suspend 方法的话可以实现并发执行的效果。

aysnc 返回一个 Deferred 对象,Deferred 是一个轻量级阻塞式对象,可以调用 Deferred.await()延迟获取返回结果

Deferred 也是一个 Job,所以也可以取消操作

  1. 代码
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)
}
复制代码
  1. 日志
日志:  A
日志:  B
日志:  执行总时长:3022
复制代码
  1. 结论
    上一节中代码执行总耗时 5105,本节总耗时 3022。这说明两个 async 是并发执行的

惰性启动的 async

async 可以通过将 start 参数设置为 CoroutineStart.LAZY 而变为惰性的。 在这个模式下,只有结果通过 await 获取的时候协程才会启动,或者在 Job 的 start 函数调用的时候

  1. 代码
fun main() = runBlocking {
    val deferred = async (start = CoroutineStart.LAZY){
        delay(2000)
        log(A)
        "async执行完成"
    }
    log(deferred.await())
}
复制代码
  1. 日志
日志:  A
日志:  async执行完成
复制代码
  1. 结论

    必须调用 await 或 start 才能启动,

使用 async 的结构性并发

协程体作用域中并发的多个 async,有一个发生异常其它的 async 也会被取消

  1. 代码
fun main() = runBlocking {
    async {
        log("吃饭aa,别bb")
        delay(100)
        throw IllegalArgumentException("打你一嘴巴子,你再bb")
    }
   async {
       log("就bb,咋地")
       delay(300)
       log("bb完了")
   }
    log("程序结束")
}
复制代码
  1. 日志
日志:  程序结束
日志:  吃饭aa,别bb
日志:  就bb,咋地
Exception in thread "main" java.lang.IllegalArgumentException: 打你一嘴巴子,你再bb
	at SuspendMethodKt$main$1$1.invokeSuspend(SuspendMethod.kt:55)
复制代码
  1. 记录

    当第一个 async 抛出异常后,第二个 async 后面 “bb 完了”的日志没有打印,说了第二个 async 也同步被取消了。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享