Kotlin Coroutines-如何阻止等待/加入所有工作? [英] Kotlin Coroutines - How to block to await/join all jobs?

查看:131
本文介绍了Kotlin Coroutines-如何阻止等待/加入所有工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是Kotlin/Coroutines的新手,所以希望我只是缺少一些东西/无法完全理解如何为我要解决的问题构建代码.

I am new to Kotlin/Coroutines, so hopefully I am just missing something/don't fully understand how to structure my code for the problem I am trying to solve.

基本上,我正在获取一个字符串列表,对于列表中的每个项目,我都希望将其发送到另一种方法来工作(进行网络调用并根据响应返回数据). (编辑 :)我希望所有调用同时启动,并阻塞直到所有调用完成/响应被执行,然后返回一个包含每个响应信息的新列表.

Essentially, I am taking a list of strings, and for each item in the list I want to send it to another method to do work (make a network call and return data based on the response). (Edit:) I want all calls to launch concurrently, and block until all calls are done/the response is acted on, and then return a new list with the info of each response.

我可能还不太了解何时使用启动/异步,但是我尝试同时跟踪启动(使用joinAll)和异步(使用await).

I probably don't yet fully understand when to use launch/async, but I've tried to following with both launch (with joinAll), and async (with await).

fun processData(lstInputs: List<String>): List<response> {

    val lstOfReturnData = mutableListOf<response>()

    runBlocking {
        withContext(Dispatchers.IO) {
            val jobs = List(lstInputs.size) {
                launch {
                    lstOfReturnData.add(networkCallToGetData(lstInputs[it]))
                }
            }
            jobs.joinAll()
        }
    }

    return lstofReturnData

我希望发生的是,如果我的lstInputs的大小为120,则在加入所有作业时,我的lstOfReturnData的大小也应该为120.

What I am expecting to happen, is if my lstInputs is a size of 120, when all jobs are joined, my lstOfReturnData should also have a size of 120.

实际发生的是不一致的结果.我将运行一次,并且在最终列表中获得118,再次运行,它是120,再次运行,它是117,依此类推.在networkCallToGetData()方法中,我正在处理任何异常,至少返回一些东西对于每个请求,无论网络呼叫是否失败.

What actually is happening is inconsitent results. I'll run it once, and I get 118 in my final list, run it again, it's 120, run it again, it's 117, etc. In the networkCallToGetData() method, I am handling any exceptions, to at least return something for every request, regardless if the network call fails.

任何人都可以帮助解释为什么我得到的结果不一致,以及我需要做些什么来确保我进行适当的阻止并继续所有工作,然后再继续?

Can anybody help explain why I am getting inconsistent results, and what I need to do to ensure I am blocking appropriately and all jobs are being joined before moving on?

推荐答案

mutableListOf()创建一个不是线程安全的ArrayList.
尝试改用ConcurrentLinkedQueue.

mutableListOf() creates an ArrayList, which is not thread-safe.
Try using ConcurrentLinkedQueue instead.

此外,您是否使用Kotlin/Kotlinx.coroutine的稳定版本(而不是旧的实验版本)?在稳定版本中,由于引入了结构化并发,因此无需编写jobs.joinAll anymore. launchrunBlocking的扩展功能,它将在runBlocking范围内启动新协程,并且runBlocking范围将自动等待所有启动的作业完成.因此,上面的代码可以简化为

Also, do you use the stable version of Kotlin/Kotlinx.coroutine (not the old experimental one)? In the stable version, with the introduction of structured concurrency, there is no need to write jobs.joinAll anymore. launch is an extesion function of runBlocking which will launch new coroutines in the scope of the runBlocking and the runBlocking scope will automatically wait for all the launched jobs to finsish. So the code above can be shorten to

val lstOfReturnData = ConcurrentLinkedQueue<response>()
runBlocking {
        lstInputs.forEach {
            launch(Dispatches.IO) {
                lstOfReturnData.add(networkCallToGetData(it))
            }
        }
}
return lstOfReturnData

这篇关于Kotlin Coroutines-如何阻止等待/加入所有工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆