美文网首页Kotlin-CoroutinesAndroid开发Android开发经验谈
Kotlin(十九)协程(组合挂起函数)

Kotlin(十九)协程(组合挂起函数)

作者: 大虾啊啊啊 | 来源:发表于2020-11-04 14:48 被阅读0次

1.默认顺序

我们有两个耗时操作doSomthingOne和doSomthingTwo,例如网络请求数据,但是在协程中的代码执行顺序是按顺序的,等待doSomthingOne执行完在执行doSomthingTwo。

package com.example.kotlin01

import kotlinx.coroutines.*

 suspend fun main() {
     runBlocking {
         var job = launch {
             var result1 = doSomthingOne()
             println(result1)
             var result2 = doSomthingTwo()
             println(result2)
             println(result1+result2)
         }
     }

}

suspend fun doSomthingOne(): Int {
    delay(2000)
    return 13
}


suspend fun doSomthingTwo(): Int {
    delay(1000)
    return 15
}

13
15
28

2.使用 async 并发

第一个例子中,执行两个耗时操作是按照顺序同步执行的,但是很多时候,我们在做请求网络耗时操作的时候希望是异步,并发执行的。我们通过async 类似launch单独启动协程,返回的是Deferred非阻塞对象,可以调用await()取出返回值。Deferred 也实现了job接口,可以取消协程。以下我们通过同步的代码完成异步并发的业务

package com.example.kotlin01

import kotlinx.coroutines.*

 suspend fun main() {
     runBlocking {

         var result1 = async {
             doSomthingOne()
         }
         println("${result1.await()}")
         var result2 = async {
             doSomthingTwo()
         }
         println("${result2.await()}")
         println("${result1.await()}+${result2.await()}")
     }

}

suspend fun doSomthingOne(): Int {
    delay(2000)
    return 13
}


suspend fun doSomthingTwo(): Int {
    delay(1000)
    return 15
}


13
15
13+15

以上开启了两个协程,分别打印了第一个结果和第二个结果。

3.惰性启动

可以设置async的start = CoroutineStart.LAZY,这样只有手动调用deffer的start方法或者await方法,协程才会执行

package com.example.kotlin01

import kotlinx.coroutines.*

 suspend fun main() {
     runBlocking {

         var result1 = async(start = CoroutineStart.LAZY) {
             doSomthingOne()
         }
         var result2 = async(start = CoroutineStart.LAZY) {
             doSomthingTwo()
         }
//
     }

}

suspend fun doSomthingOne(): Int {

    delay(2000)
    println("doSomthingOne")
    return 13
}


suspend fun doSomthingTwo(): Int {
    delay(1000)
    println("doSomthingTwo")
    return 15
}

设置 CoroutineStart.LAZY之后,没有手动调用start和await方法,doSomthingOne和doSomthingTwo两个函数没有执行

package com.example.kotlin01

import kotlinx.coroutines.*

 suspend fun main() {
     runBlocking {

         var result1 = async(start = CoroutineStart.LAZY) {
             doSomthingOne()
         }
         var result2 = async(start = CoroutineStart.LAZY) {
             doSomthingTwo()
         }
         result1.start()
         result2.start()
         println("${result1.await()}+${result2.await()}")
     }

}

suspend fun doSomthingOne(): Int {

    delay(2000)
    println("doSomthingOne")
    return 13
}


suspend fun doSomthingTwo(): Int {
    delay(1000)
    println("doSomthingTwo")
    return 15
}

doSomthingTwo
doSomthingOne
13+15

手动调用之后,两个协程执行了。

4.异步风格的函数

package com.example.kotlin01

import kotlinx.coroutines.*

 suspend fun main() {
     runBlocking {
         var result1 = doSomthingOneAsync()
         var result2 = doSomthingTwoAsync()
         println("${result1.await()} and ${result2.await()}")
     }

}
fun doSomthingOneAsync() = GlobalScope.async {
    doSomthingOne()
}
fun doSomthingTwoAsync() = GlobalScope.async {
    doSomthingTwo()
}


suspend fun doSomthingOne(): Int {

    delay(2000)
    println("doSomthingOne")
    return 13
}


suspend fun doSomthingTwo(): Int {
    delay(1000)
    println("doSomthingTwo")
    return 15
}

doSomthingTwo
doSomthingOne
13 and 15

以上的方式的缺点在于,如果 var result2 = doSomthingTwoAsync()这行出现错误,程序抛出异常,doSomthingOneAsync会继续执行,因为其协程作用域是 GlobalScope。

5.使用 async 的结构化并发

为了防止第4点的问题,我们通过使用 async 的结构化并发解决

package com.example.kotlin01

import kotlinx.coroutines.*

suspend fun main() {
    println("${doSum()}")
}

suspend fun doSum(): Int = coroutineScope {
    var result1 = async { doSomthingOne() }
    var result2 = async { doSomthingTwo() }
    result1.await() + result2.await()
}

suspend fun doSomthingOne(): Int {

    delay(2000)
    println("doSomthingOne")
    return 13
}

suspend fun doSomthingTwo(): Int {
    delay(1000)
    println("doSomthingTwo")
    return 15
}

doSomthingTwo
doSomthingOne
28

如果doSum函数出现异常,那么期作用域内的协程都会被取消。从main函数来看,两个协程也是并发执行的。

相关文章

网友评论

    本文标题:Kotlin(十九)协程(组合挂起函数)

    本文链接:https://www.haomeiwen.com/subject/okrgvktx.html