编写挂起函数
默认顺序
当需要按顺序调用挂起函数时,可以直接顺序书写来调用它们
fun main() = runBlocking {
val time = measureTimeMillis {
doSomethingUsefulOne()
doSomethingUsefulTwo()
}
println(time)
}
使用 async 并发
可以使用async
函数使得任务并发执行,它在概念上与launch
类似,但不同之处在于launch
返回一个Job
并且不携带任何结果,而async
返回了一个Deferred
,一个轻量级非阻塞的future
,可以使用await
来获取它的执行结果,但Deferred
也是一个Job
,可以和Job
一样被控制
runBlocking {
val time = measureTimeMillis {
val one = async { doSomethingUsefulTwo() }
val two = async { doSomethingUsefulTwo() }
"result is ${one.await() + two.await()}"
}
}
惰性启动 async
可以设置协程的start
参数为LAZY
,从而使得async
变为惰性
只有当获取async
值或者调用start
方法时,async
的结果才会被计算
但如果直接调用await
输出值,将会导致async
顺序执行,因为await
将启动协程并等待其完成
val time = measureTimeMillis {
val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
one.start()
two.start()
println("result = ${one.await() + two.await()}")
}
异步风格的函数
这种风格是其它语言中的风格,不建议在Kotlin
中这样使用
可以使用异步协程构建器定义异步调用的异步风格函数,并使用GlobalScope
来取消结构化并发,使用..Async
后缀来定义这种函数,以强调它们仅仅是用于启动异步计算
@OptIn(DelicateCoroutinesApi::class)
fun somethingUsefulTwoAsync() = GlobalScope.async {
doSomethingUsefulOne()
}
@OptIn(DelicateCoroutinesApi::class)
fun somethingUsefulOneAsync() = GlobalScope.async {
doSomethingUsefulTwo()
}
GlobalScope
是一个精密的 API,在调用它时,很容易导致意外创建资源或者内存泄漏的问题,要使用它需要加上@OptIn(DelicateCoroutinesApi::class)
注解