【问题标题】:parallel calls in kotlin without blocking main threadkotlin 中的并行调用而不阻塞主线程
【发布时间】:2022-02-01 15:01:24
【问题描述】:

我正在学习 kotlin 协程和作用域,无法理解如何通过不阻塞主线程来触发并行调用。正如您在以下示例中看到的,2 个调用是并行触发的,但是对 .awaitAll() 的调用似乎阻塞了主线程,因为我希望在“1.Current 线程”之前打印“我被阻止的消息” ...“ 信息。这是实现此类查询的正确方法吗?

当前输出:
主线程 main
...(5 秒后)...
1.当前线程 DefaultDispatcher-worker-1
1.当前线程 DefaultDispatcher-worker-3
我被屏蔽了

预期输出:
主线程 main
我被屏蔽了
...(5 秒后)...
1.当前线程 DefaultDispatcher-worker-1
1.当前线程DefaultDispatcher-worker-3

class FindItinerariesComposable(private val providers: List<FindItineraries>) : FindItineraries {
    override suspend fun itinerariesForOriginDestination(origin: String, destination: String): List<Itinerary> {
        println("Main thread ${Thread.currentThread().name}")
        return coroutineScope {
            val stream = providers.stream()
                .map {
                    async {
                        it.itinerariesForOriginDestination(origin, destination)
                    }
                }
                .toList()
                .awaitAll()
                .flatten()
            println("I'm blocked")
            stream
        }
    }
}


class FindItinerariesInFlightProvider(private val httpClient: HttpClient) : FindItineraries {

    override suspend fun itinerariesForOriginDestination(origin: String, destination: String): List<Itinerary> {
        withContext(Dispatchers.IO) {
            delay(5000)
            println("1.Current thread  ${Thread.currentThread().name}")
        }
        return listOf(Itinerary("bue", "MIA", "TEST"))
    }
}

fun main() = runBlocking<Unit> {
    val service = FindItinerariesComposable(listOf(FindItinerariesInFlightProvider(HttpClient()),
        FindItinerariesInFlightProvider(HttpClient())))
    launch {
        service.itinerariesForOriginDestination("BUE", "MIA")
    }
}

【问题讨论】:

    标签: multithreading kotlin-coroutines


    【解决方案1】:

    看来你也想吃蛋糕。

    在让主线程继续执行任何其他任务之前,您希望在主线程上获得所有这些调用的结果。

    你也不想阻塞主线程。

    如果你想要后者,那么你必须引入并发,主线程执行其他任务并且不需要那些结果才能继续。

    这可能意味着您正在做的设计将发生根本性的变化。如果您有任何依赖于这些结果的代码,则必须添加更多使用某些替代值或模型值的代码,直到实际结果可用为止。您还必须将当前接收结果并对其进行操作的任何代码移动到协程中。

    这是一个大纲:

    fun main() {
        val service = initializeService()
        val myScope = CoroutineScope()
        myScope.launch {
            val itineraries = service.itinerariesForOriginDestination("BUE", "MIA")
            // do things with itineraries
        }
        // do other things, don't let the main function end
        myScope.cancel() // do this at the very end, when you no longer
                         // need coroutines
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-05-21
      • 2018-12-29
      • 1970-01-01
      • 2019-07-23
      • 2021-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多