Kotlin等待不暂停吗?

时间:2018-09-20 21:13:56

标签: kotlin kotlinx.coroutines

我在Kotlin中有以下代码

import kotlinx.coroutines.experimental.async
import kotlinx.coroutines.experimental.delay
import kotlinx.coroutines.experimental.runBlocking

fun main(args: Array<String>) {

    runBlocking {
        val async1 = async {
            println("1st")
            delay(2000)
            println("1st end")
        }
        val async2 = async {
            println("2nd")
            delay(1000)
            println("2nd end")
        }

        async1.await()
        async2.await()

        println("end")
    }
}

输出为

1st
2nd
2nd end
1st end
end

我的理解是await()是一个暂停函数,这意味着执行被“暂停”在那里。因此,我认为实际上首先执行async1,然后执行async2。所以我希望输出是

1st
1st end
2nd
2nd end    
end

显然发生的是,async1async2都并行执行,可以看作async1的输出夹在async2的输出之间

所以我现在的具体问题是:为什么Kotlin没有在async1上暂停,而是同时启动async2

2 个答案:

答案 0 :(得分:1)

await()将挂起它在其中运行的协程-这是您的主要块(并且线程runBlocking()正在运行,因为它正在阻塞),因此不会调用async2.await(),除非{ {1}}完成。 但是由于async1函数的执行是立即开始的,并且默认情况下将在后台线程池中执行,因此不会被阻塞。 您可以通过添加

进行检查
async()

然后看到,“ between”将始终在“ 1st end”之后打印

如果您希望协程顺序运行,请使用 async1.await() println("between") async2.await() 构建器(或者在大多数情况下,在这种情况下根本不需要使用协程)

异步/等待的想法是并行运行任务,并且在等待其中一个任务的结果时不要阻塞其他任务。

答案 1 :(得分:0)

  

为什么Kotlin没有在async1上暂停,而是同时启动async2

async在后​​台生成一个新任务。任务立即开始执行。您无法控制其暂停,并且在整个用例中,它永远不会被暂停。我们经常使用async将阻止任务提交到线程池。

await暂停当前协程,直到任务完成并产生结果。它对任务的执行没有影响。即使您从不致电await,任务也将完成。

如果您特别想仅在调用await时触发任务,则可以指定start = LAZY

runBlocking {
    val async1 = async(start = LAZY) {
        println("1st")
        delay(2000)
        println("1st end")
    }
    val async2 = async(start = LAZY) {
        println("2nd")
        delay(1000)
        println("2nd end")
    }

    async1.await()
    async2.await()

    println("end")
}

这将按照您期望的顺序可靠地打印。