简体   繁体   English

等待多个异步时 GlobalScope 和 runBlocking 的区别

[英]Difference between GlobalScope and runBlocking when waiting for multiple async

I have a Kotlin Backend/server API using Ktor, and inside a certain endpoint's service logic I need to concurrently get details for a list of ids and then return it all to the client with the 200 response.我有一个使用 Ktor 的 Kotlin 后端/服务器 API,在某个端点的服务逻辑中,我需要同时获取 ID 列表的详细信息,然后使用 200 响应将其全部返回给客户端。

The way I wanted to do it is by using async{} and awaitAll()我想这样做的方式是使用 async{} 和 awaitAll()

However, I can't understand whether I should use runBlocking or GlobalScope.但是,我不明白我应该使用 runBlocking 还是 GlobalScope。 What is really the difference here?这到底有什么区别?

fun getDetails(): List<Detail> {
    val fetched: MutableList<Details> = mutableListOf()

    GlobalScope.launch { --> Option 1
    runBlocking { ---> Option 2
    Dispatchers.IO --> Option 3 (or any other dispatcher ..)

         myIds.map { id ->
             async {
                 val providerDetails = getDetails(id)
                 fetched += providerDetails
             }
         }.awaitAll()
     }
     return fetched
}

launch starts a coroutine that runs in parallel with your current code, so fetched would still be empty by the time your getDetails() function returns. launch启动一个与当前代码并行运行的协程,因此在getDetails()函数返回时fetched仍为空。 The coroutine will continue running and mutating the List that you have passed out of the function while the code that retrieved the list already has the reference back and will be using it, so there's a pretty good chance of triggering a ConcurrentModificationException.协程将继续运行并改变您从函数中传递出来的列表,而检索列表的代码已经返回引用并将使用它,因此很有可能触发 ConcurrentModificationException。 Basically, this is not a viable solution at all.基本上,这根本不是一个可行的解决方案。

runBlocking runs a coroutine while blocking the thread that called it. runBlocking运行协程,同时阻塞调用它的线程。 The coroutine will be completely finished before the return fetched line, so this will work if you are OK with blocking the calling thread.协程将在return fetched的行之前完全完成,因此如果您愿意阻塞调用线程,这将起作用。

Specifying a Dispatcher isn't an alternative to launch or runBlocking .指定 Dispatcher 不能替代launchrunBlocking It is an argument that you can add to either to determine the thread pool used for the coroutine and its children.这是一个参数,您可以将其添加到其中一个以确定用于协程及其子程序的线程池。 Since you are doing IO and parallel work, you should probably be using runBlocking(Dispatchers.IO) .由于您正在进行 IO 和并行工作,因此您可能应该使用runBlocking(Dispatchers.IO)

Your code can be simplified to avoid the extra, unnecessary mutable list:可以简化您的代码以避免额外的、不必要的可变列表:

fun getDetails(): List<Detail> = runBlocking(Dispatchers.IO) {
    myIds.map { id ->
        async {
             getDetails(id)
        }
    }.awaitAll()
}

Note that this function will rethrow any exceptions thrown by getDetails() .请注意,此函数将重新抛出getDetails()抛出的任何异常。


If your project uses coroutines more generally, you probably have higher level coroutines running, in which case this should probably be a suspend function (non-blocking) instead:如果你的项目更普遍地使用协程,你可能有更高级别的协程在运行,在这种情况下,这可能应该是一个挂起函数(非阻塞):

suspend fun getDetails(): List<Detail> = withContext(Dispatchers.IO) {
    myIds.map { id ->
        async {
             getDetails(id)
        }
    }.awaitAll()
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 MainCoroutineRule 和 runBlocking 的区别 - Difference between MainCoroutineRule and runBlocking 使用协程在 kotlin 中停止无限 function - async 和 GlobalScope.async 之间的区别 - Stop infinite function in kotlin using coroutines - difference between async and GlobalScope.async Kotlin 中 globalScope 、 cooruntineScope 和 viewScope 之间的区别 - Difference between globalScope , corountineScope and viewScope in Kotlin 了解 runBlocking 和 coroutineScope 之间的行为差异 - Understanding difference in behavior between runBlocking and coroutineScope Kotlin 协程 GlobalScope.launch 与 runBlocking - Kotlin coroutines GlobalScope.launch vs runBlocking 在没有 viewmodelScope 和 runBlocking 或 GlobalScope 的情况下调用 RoomDB 操作 - call RoomDB operations without viewmodelScope and runBlocking or GlobalScope kotlin GlobalScope,kotlin.coroutines中不提供runBlocking。* - kotlin GlobalScope, runBlocking is not available in kotlin.coroutines.* 使用 GlobalScope.launch 和 CoroutineScope().launch 启动协程有区别吗? - Is there a difference between using GlobalScope.launch and CoroutineScope().launch to launch a coroutine? Kotlin 协程 runBlocking async - Kotlin coroutines runBlocking async Kotlin runBlocking 和 async with return - Kotlin runBlocking and async with return
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM