Kotlin协同路由异步等待序列
你能解释一下这两段代码之间的区别吗。第一次打印421,但第二次打印606。为什么第一个是平行的,第二个是顺序的Kotlin协同路由异步等待序列,kotlin,coroutine,kotlin-coroutines,Kotlin,Coroutine,Kotlin Coroutines,你能解释一下这两段代码之间的区别吗。第一次打印421,但第二次打印606。为什么第一个是平行的,第二个是顺序的 fun main(args: Array<String>) = runBlocking { var time = measureTimeMillis { val one = async { one() } val two = async { two() } val int1 = one.await()
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
}
fun main(args:Array)=运行阻塞{
var时间=测量值{
val one=async{one()}
val two=async{two()}
val int1=1.await()
val int2=2.await()
println(int1+int2)
}
println(时间)
时间=测量值{
val one=async{one()}.await()
val two=async{two()}.await()
println(一加二)
}
打印(时间)
}
suspend fun one():Int{
延迟(200)
返回12
}
suspend fun two():Int{
延迟(400)
返回23
}
在第一个变量中,两个异步调用都会得到一个延迟
。如图所示,延迟对象可能处于多个状态。从外部看,该状态现在要么是新的,要么是活动的,但肯定还没有完成。但是,在第二个变量上,第一个async Wait已经需要一个completed
状态,否则就不能有任何值。但是,在您的async{one()}.await()
上,第二个async
还不知道。
还要注意,await()
的返回值现在是Int
,不再是Deferred
,因此此时必须已经执行了协同程序。也检查一下
换言之:
val one = async { one() }
val two = async { two() }
one
和two
现在都是延迟的
。尚未调用(或可能尚未调用)。只要你调用one.await()
它可能已经启动了one
和two
,仅仅因为它有足够的资源(即使你没有在代码中的任何地方使用two.await()
)
然而,关于第二种变体:
val one = async { one() }.await()
val two = async { two() }.await()
即使它为async{one()}
创建一个协程,它也必须立即将值设置为one
,因为您正在对其调用wait()
。one
和two
的类型都是Int
。因此,一旦第一行被命中,异步代码就需要立即执行。到那时,当我们等待第一个异步调用的值时,没有人知道必须执行另一个异步调用。如果第一个进程没有等待
,则协同进程将再次并行执行,例如:
val one = async { one() }
val two = async { two() }.await()
将并行执行one()
和two()
因此,也许这可以概括为:只有那些协同路由可以在等待中并行执行,而这些等待在那时是已知的/产生的
val one = async { one() }
val two = async { two() }
val int1 = one.await()
val int2 = two.await()
它的作用是:
它的作用是:
async
。恰当的成语是
val one = withContext(Dispatchers.Default) { one() }
val two = withContext(Dispatchers.Default) { two() }
在Marko Topolnik的回答之后,我尝试了不同的变化,我认为这是可以接受的答案。但有一件有趣的事情是,若我启动协同程序而不是调用wait,那个么函数将启动但不会结束。下面是我的代码
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
}
fun main(args:Array)=运行阻塞{
var时间=测量值{
val one=async{one(1)}
val two=async{two(1)}
val int1=1.await()
val int2=2.await()
}
println(“时间:$time”)
时间=测量值{
val one=async{one(2)}.await()
val two=async{two(2)}.await()
}
println(“时间:$time”)
时间=测量值{
val one=async{one(3)}
val two=async{two(3)}
}
println(“时间:$time”)
}
暂停乐趣一(迭代:Int):Int{
println(“func1开始,迭代$iteration”)
延迟(200)
println(“func1结束,迭代$iteration”)
返回12
}
暂停乐趣二(迭代:Int):Int{
println(“func2开始,迭代$iteration”)
延迟(400)
println(“func2结束,迭代$iteration”)
返回23
}
而产出是,
func1开始,迭代1func2开始,迭代1
func1结束,迭代1
func2结束,迭代1
时间:430
func1开始,迭代2
函数1结束,迭代2
func2开始,迭代2
func2结束,迭代2
时间:607
func1开始,迭代3
时间:2
func2开始,迭代3 进程结束,退出代码为0拇指规则:
- 在不需要并行执行时使用withContext
- 仅当需要并行执行时才使用异步。withContext和async都可用于获得启动时无法获得的结果
- 使用withContext返回单个任务的结果。'
- 对并行运行的多个任务的结果使用异步
查看更多详细信息我不确定如何获得这两个值。12 + 23 = 35. 我无法理解你到底是怎么得到421和606的。也许确认一下你在问题中输入的内容,然后我会看看我是否能帮上忙。异步上的等待通常替换为“withContext(yourProviderThread){},然后不需要等待,但无论哪种方式,异步{someMethod}.Await()都是可以接受的,如果您不排队等待,那么您可以轻松地执行一个.Await()+两个.Await()这也应该给出相同的值。但很难推测何时输出不一致。421/606是运行变量1和变量2所用的毫秒;-)与其说它知道多少,不如说它知道多少;更多的是你告诉。在第二个变量中,你告诉编译器在之前等待第一个协程的执行继续(在创建第二个协同程序之前)。
await
是一个非挂起函数。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
}