async 用于处理挂起函数的并发
在概念上,async 就类似于 launch。它启动了一个单独的协程,这是一个轻量级的线程并与其它所有的协程一起并发的工作。不同之处在于 launch
返回一个 Job 并且不附带任何结果值,而 async
返回一个 Deferred —— 一个轻量级的非阻塞 future, 这代表了一个将会在稍后提供结果的 promise。你可以使用 .await()
在一个延期的值上得到它的最终结果, 但是 Deferred
也是一个 Job
,所以如果需要的话,你可以取消它。
suspend fun doSomethingUsefulOne(): Int {
delay(1000L) // 假设我们在这里做了些有用的事
return 13
}
suspend fun doSomethingUsefulTwo(): Int {
delay(1000L) // 假设我们在这里也做了一些有用的事
return 29
}
fun main() = runBlocking<Unit> {
val time = measureTimeMillis {
val one = async { doSomethingUsefulOne() }
val two = async { doSomethingUsefulTwo() }
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
}
val time = measureTimeMillis {
// 当添加了 CoroutineStart.LAZY, 只有被await 或 start 协程才会被调用
val one = async(start = CoroutineStart.LAZY) { doSomethingUsefulOne() }
val two = async(start = CoroutineStart.LAZY) { doSomethingUsefulTwo() }
// 执行一些计算
one.start() // 启动第一个
two.start() // 启动第二个
println("The answer is ${one.await() + two.await()}")
// 注意,这里如果不实用start,消耗的时间仍是两者之和
}
我们可以对这些挂起函数进行封装
// somethingUsefulOneAsync 函数的返回值类型是 Deferred<Int>
fun somethingUsefulOneAsync() = GlobalScope.async {
doSomethingUsefulOne()
}
// somethingUsefulTwoAsync 函数的返回值类型是 Deferred<Int>
fun somethingUsefulTwoAsync() = GlobalScope.async {
doSomethingUsefulTwo()
}
// 如果在 concurrentSum 函数内部发生了错误,并且它抛出了一个异常,
// 所有在作用域中启动的协程都将会被取消。
suspend fun concurrentSum(): Int = coroutineScope {
val one = async { doSomethingUsefulOne() }
val two = async { doSomethingUsefulTwo() }
one.await() + two.await()
}
fun main() {
val time = measureTimeMillis {
// 我们可以在协程外面启动异步执行
val one = somethingUsefulOneAsync()
val two = somethingUsefulTwoAsync()
// 但是等待结果必须调用其它的挂起或者阻塞
// 当我们等待结果的时候,这里我们使用 `runBlocking { …… }` 来阻塞主线程
runBlocking {
// 这里,它们就会并发执行
println("The answer is ${one.await() + two.await()}")
}
}
println("Completed in $time ms")
}
网友评论