如何等待所有协程完成?

时间:2019-04-29 13:08:54

标签: kotlin kotlin-coroutines

我正在启动协程,并且希望它在恢复执行主线程之前完成。

我的简化代码如下:

fun hello() {
    for (i in 0..100) {
        println("hello")
    }
}

fun main(args: Array<String>) {
    val job = GlobalScope.launch { hello() } //launch parallel 
    GlobalScope.launch { job.join() }  //try to wait for job to finish
    print("done")
}

问题在于,由于job.join()必须位于协程中,因此执行的主行被推迟为“完成”,因此输出如下所示:

donehello
hello
hello
hello

我想等待作业完成,就像在Go中使用sync.WaitGroup一样。所以我的输出将确定地看起来像这样:

hello
hello
hello
hello
...
done

我如何做到这一点?

2 个答案:

答案 0 :(得分:2)

实际上,对于您的样本,job.join()是确保此时等待直到给定作业完成的方式。不幸的是,您再次将其打包在GlobalScope.launch中,这只是将等待的内容放入了后台线程。因此,它比您预期的更早到达了done,并且在我的机器上它甚至没有打印任何hello(但可以)。

我假设您使用launch是因为join只能从协程或其他暂停函数调用?对于您的示例,只需将suspend添加到main就足够了,例如:

suspend fun main() {
  val job = GlobalScope.launch { hello() }
  job.join()
  print("done")
}

或者您可以使用runBlocking并将main包裹起来,例如:

fun main() = runBlocking {
  val job = launch { hello() }      
  job.join()
  print("done")
}

现在免责声明...您可能希望在继续之前(如果您尚未这样做的话)查阅以下资源:

  1. Coroutine basics
  2. The reason to avoid GlobalScopeRoman Elizarov
  3. Concurrent coroutines - Concurrency is not parallelism@s1m0nw1

答案 1 :(得分:0)

为什么不在协同程序中打印消息?您可以通过执行以下操作来实现所需的目标:

GlobalScope.launch {
    hello()
    print("done")
}

或者您可以运行协程并阻塞直到完成,即使这违反了协程的目的:

runBlocking { GlobalScope.launch { hello() }
print("done")