代码之家  ›  专栏  ›  技术社区  ›  toffor

Kotlin协程异步等待序列

  •  2
  • toffor  · 技术社区  · 6 年前

    你能解释一下这两段代码的区别吗。第一次打印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
    }
    
    3 回复  |  直到 5 年前
        1
  •  34
  •   Marko Topolnik    6 年前
    val one = async { one() }
    val two = async { two() }
    val int1 = one.await()
    val int2 = two.await()
    

    它的作用是:

    1. 生成任务1
    2. 生成任务二
    3. 等待任务一
    4. 等待任务二

    val one = async { one() }.await()
    val two = async { two() }.await()
    

    1. 生成任务1
    2. 等待任务一
    3. 生成任务二
    4. 等待任务二

    这里没有并发,它是纯顺序代码。事实上,对于顺序执行,您甚至不应该使用 async . 恰当的成语是

    val one = withContext(Dispatchers.Default) { one() }
    val two = withContext(Dispatchers.Default) { two() }
    
        2
  •  4
  •   Roland    6 年前

    Deferred<Int> 对于两个异步调用。作为 the documentation of Deferred 很好地显示了延迟对象可能处于多个状态。从外面看,这个州现在 new active completed 否则你不能有任何价值。但是在你的 async{one()}.await() 第二个 async 还不知道。 await() 是现在 Int 而不是 推迟 再也没有了,所以协同程序必须在那时执行。同时检查 the documentation of await() .

    val one = async { one() }
    val two = async { two() }
    

    两者 one two one.await() 它可能已经开始了 two.await() 代码中的任何地方)。

    val one = async { one() }.await()
    val two = async { two() }.await()
    

    即使它为 async {one()} 马上,因为你在打电话 两者都是 内景 await ,协同程序将再次并行执行,例如:

    val one = async { one() }
    val two = async { two() }.await()
    

    将执行 one() two()

        3
  •  0
  •   toffor    6 年前

    在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


    函数2结束,迭代1

    func1开始,迭代2
    函数1结束,迭代2
    func2开始,迭代2
    函数2结束,迭代2
    时间:607
    func1开始,迭代3
    时间:2
    func2开始,迭代3

        4
  •  0
  •   MohamedHarmoush    3 年前

    经验法则:

    • 使用 当您不需要并行执行时。
    • 只有当你需要并行执行的时候。两者 带上下文 可以用来得到发射时不可能得到的结果。
    • 使用 返回单个任务的结果

    this 更多细节