如何等待所有协程完成?

nz_*_*_21 5 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")
}
Run Code Online (Sandbox Code Playgroud)

问题是,因为job.join()需要在一个协程内,执行的主线被推迟到“完成”,所以输出看起来像这样:

donehello
hello
hello
hello
Run Code Online (Sandbox Code Playgroud)

我想等待工作完成,就像sync.WaitGroup在 Go 中使用一样。所以我的输出肯定是这样的:

hello
hello
hello
hello
...
done
Run Code Online (Sandbox Code Playgroud)

我该如何实现?

Rol*_*and 9

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

我假设您使用了launch因为join只能从协程或其他挂起函数调用?对于您的示例,只需添加suspendmain,例如:

suspend fun main() {
  val job = GlobalScope.launch { hello() }
  job.join()
  print("done")
}
Run Code Online (Sandbox Code Playgroud)

或者你可以使用它runBlockingmain用它包裹,例如:

fun main() = runBlocking {
  val job = launch { hello() }      
  job.join()
  print("done")
}
Run Code Online (Sandbox Code Playgroud)

现在免责声明......在继续之前,您可能需要咨询以下来源(如果您还没有这样做):

  1. 协程基础
  2. 避免GlobalScope原因罗马Elizarov
  3. 并行协同程序-并发不能并行通过@ s1m0nw1