如何启动并行协程并返回结果

Posted

技术标签:

【中文标题】如何启动并行协程并返回结果【英文标题】:How to launch parallel coroutines and return result 【发布时间】:2020-11-05 10:46:32 【问题描述】:

我正在尝试编写一个异步运行 2 个操作并使用 Kotlin 协程返回结果的函数。例如,我希望我的 getData 方法大致同时运行我的两个 longRunningOperationX 方法,这样我可以更快地获得组合结果:

fun getData(): String 
  val stringOne = longRunningStringOperationOne()
  val stringTwo = longRunningStringOperationTwo()
  return stringOne + stringTwo

在 Kotlin 中,我可以使用 launchasync 方法运行这些操作。

fun getData(): String 
  GlobalScope.launch  
    val stringOne = async  longRunningStringOperationOne() 
    val stringTwo = async  longRunningStringOperationTwo() 
    println("result: $stringOne + $stringTwo")
    // return "result: $stringOne + $stringTwo" <- not allowed
  
  return "?"

但是,正如您可能知道的那样,Coroutine 范围内的操作结果在 GlobalScope 之外是不可访问的,所以我的方法只需要在我长时间运行的操作之前返回它当时的内容完成。

因此,考虑到这个问题空间 - 一个返回结果的非暂停(不是 kotlin suspend fun)函数 - 我如何异步(并行)运行两个长时间运行的操作,但在返回之前等待它们的结果使用Kotlin 协程?

【问题讨论】:

您可以等待并使用runBlocking 函数从非挂起函数返回一些结果,但它会阻塞调用它的线程。您不能在不阻塞当前线程的情况下让非挂起函数等待协程的结果。 【参考方案1】:

您需要使用Structured Concurrency 而不是全局作用域,并使用await() async 返回的作业。一种方法是这样的:

fun getData(): String 
  return runBlocking  
    val stringOne = async  longRunningStringOperationOne() 
    val stringTwo = async  longRunningStringOperationTwo() 
    "result: $stringOne.await() + $stringTwo.await()")  // will be the return value of the runBlocking lambda
  

【讨论】:

以上是关于如何启动并行协程并返回结果的主要内容,如果未能解决你的问题,请参考以下文章

如何并行进行多个 Spring Webclient 调用并等待结果?

如何获取协程的返回值

在自己的线程中运行事件循环

如何获得CreateProcess启动的进程返回的结果

从并行for循环返回结果

openmp/C++ 简单并行区域返回不一致的结果