问题描述:
场景:在协程中并发获取三个接口,需要在接口获取获取完成后,对三个返回值进行合并操作
bug:获取过程中,合并操作已经对全部变量res1,res2,res3进行操作了
所以研究了一波,原因是我的Async{}中的函数没有返回值,导致Async返回的是一个Deferred<Unit>
这样的话就不会进行阻塞了,除非函数是一个suspend
挂起函数
直接上代码,看下两者的区别
有返回值的
- code:
fun main() = runBlocking {
println("start ${System.currentTimeMillis()}")
val value1 = async { fun1() }
val value2 = async { fun2() }
val valueAdd = value1.await() + value2.await()
println("end ${System.currentTimeMillis()}")
}
suspend fun fun1() : Int{
delay(2000)
return 1
}
suspend fun fun2() : Int{
delay(2000)
return 2
}
- 打印结果
start 1620479972927
end 1620479974947
可以看到耗时2000毫秒
无返回值的
- code
fun main() = runBlocking {
println("start ${System.currentTimeMillis()}")
val value1 = async { iFun1() }
println("${value1.await() }")
println("end ${System.currentTimeMillis()}")
delay(5000)
}
fun iFun1(){
//模拟耗时操作(比如init SDK 读写文件 网络请求)
GlobalScope.launch {
delay(2000)
println("iFun1休眠结束 ${System.currentTimeMillis()}")
}
println("执行 iFun1")
}
- 打印结果
start 1620480783966
执行 iFun1
kotlin.Unit
end 1620480784011
iFun1休眠结束 1620480786015
Process finished with exit code 0
结论:Async在使用的时候如果需要并发+阻塞处理,还是需要有一个返回值进行 await()
我的处理方式是使用channel
把耗时操作返回值
进行获取并返回
- code:
fun main() = runBlocking {
println("start ${System.currentTimeMillis()}")
val value1 = async { iFun1() }
println("${value1.await() }")
println("end ${System.currentTimeMillis()}")
}
suspend fun iFun1() : Int{
val channel = Channel<Int>()
//模拟耗时操作(比如init SDK 读写文件 网络请求)
GlobalScope.launch {
delay(2000)
channel.send(1)
println("iFun1休眠结束 ${System.currentTimeMillis()}")
}
return withTimeout(3000L){
channel.receive()
}
}
- 打印结果:
start 1620481017923
iFun1休眠结束 1620481019975
1
end 1620481019977
Process finished with exit code 0
可以看到耗时2000毫秒,进行阻塞了,可以在拿到返回值后对res进行想要的操作