您能解释一下这两个代码块之间的区别吗?第一次打印421,但是第二次打印606。为什么第一个是并行的而第二个是顺序的?
fun main(args: Array<String>) = runBlocking {
var time = measureTimeMillis {
val one = async { one() }
val two = async { two() }
val int1 = one.await()
val int2 = two.await()
println(int1 + int2)
}
println(time)
time = measureTimeMillis {
val one = async { one() }.await()
val two = async { two() }.await()
println(one + two)
}
print(time)
}
suspend fun one(): Int {
delay(200)
return 12
}
suspend fun two(): Int {
delay(400)
return 23
}
答案 0 :(得分:9)
val one = async { one() }
val two = async { two() }
val int1 = one.await()
val int2 = two.await()
这是什么:
val one = async { one() }.await()
val two = async { two() }.await()
这是什么:
这里没有并发,它是纯顺序代码。实际上,对于顺序执行,您甚至都不应该使用async
。适当的成语是
val one = withContext(Dispatchers.Default) { one() }
val two = withContext(Dispatchers.Default) { two() }
答案 1 :(得分:1)
在第一个变体中,两个异步调用都获得一个Deferred<Int>
。正如the documentation of Deferred
很好地显示的那样,延迟对象可能处于几种状态。从外部看,该状态现在是new
或active
,但肯定还没有完成。但是,在第二个变体上,第一个异步等待已经已经处于completed
状态,否则那里就没有任何值。但是,您的async{one()}.await()
上的第二个async
尚不清楚。
还请注意,await()
的返回值现在是Int
,现在不再是Deferred
,因此协程必须已经执行。还要检查the documentation of await()
。
换句话说:
val one = async { one() }
val two = async { two() }
one
和two
现在都为Deferred<Int>
。尚未调用任何(或可能尚未调用)。致电one.await()
可能会同时启动one
和two
,只是因为它拥有所需的资源(即使您没有在任何地方使用two.await()
您的代码)。
但是在第二个变体上:
val one = async { one() }.await()
val two = async { two() }.await()
即使它为async {one()}
创建了一个协程,它也必须立即将一个值设置为one
,因为您正在对其调用await()
。 one
和two
的类型均为Int
。因此,一旦这些行的第一行被击中,就需要立即执行异步代码。到那时,没有人知道在等待第一个异步调用时必须执行另一个异步调用。如果第一个没有await
,协程将再次并行执行,例如:
val one = async { one() }
val two = async { two() }.await()
将并行执行one()
和two()
。
因此,也许可以总结为:只有那些在等待时才知道/产生的协程可以并行执行。
答案 2 :(得分:0)
在Marko Topolnik的答案之后,我尝试了不同的变体,我认为它是可接受的答案。但是一件有趣的事情是,如果我启动协程而不调用await,那么函数将开始但不会结束。下面是我的代码。
fun main(args: Array<String>) = runBlocking {
var time = measureTimeMillis {
val one = async { one(1) }
val two = async { two(1) }
val int1 = one.await()
val int2 = two.await()
}
println("time: $time")
time = measureTimeMillis {
val one = async { one(2) }.await()
val two = async { two(2) }.await()
}
println("time: $time")
time = measureTimeMillis {
val one = async { one(3) }
val two = async { two(3) }
}
println("time: $time")
}
suspend fun one(iteration: Int): Int {
println("func1 start, iteration $iteration")
delay(200)
println("func1 end, iteration $iteration")
return 12
}
suspend fun two(iteration: Int): Int {
println("func2 start, iteration $iteration")
delay(400)
println("func2 end, iteration $iteration")
return 23
}
输出是
func1开始,迭代1
func2开始,迭代1
func1结束,迭代1
func2结束,迭代1
时间:430
func1开始,迭代2
func1结束,迭代2
func2开始,迭代2
func2结束,迭代2
时间:607
func1开始,迭代3
时间:2
func2开始,迭代3
以退出代码0结束的过程
答案 3 :(得分:0)
拇指规则:
查看this了解更多详情