Сопрограммы Kotlin выполняют блокировку асинхронно

#kotlin #kotlin-coroutines

#kotlin #kotlin-сопрограммы

Вопрос:

Я новичок в сопрограммах и пытаюсь использовать их для вызова трудоемкого метода пару раз за меньшее время

 fun callAPI(idList: Collection<String>): List<String> {
       
        val storedIds = mutableListOf<String>()
        runBlocking {
             val ids = idList.map { data ->
                   async {timeConsumingMethod(data)}
                    }.map { it.await() }
                    storedIds.addAll(ids)

        }
        return storedIds
    }
 

Мне нужно, чтобы все вызовы timeConsumingMethod выполнялись параллельно, но я не хочу, чтобы callAPI возвращался до тех пор, пока не завершатся все TIMECONSUMINGMETHOD .

Запустив это, я вижу, что трудоемкие методы выполняются синхронно

Может кто-нибудь помочь мне понять, какую ошибку я упускаю?

Комментарии:

1. Как вы определяете, что методы выполняются синхронно?

2. в методе timeConsumingMethod выполняется регистрация, которая показывает, что выполняемый им вызов rest завершается до запуска следующего

3. использование async(Dispatchers.IO) { ... }

4. Да, потому что блокировка выполнения является однопоточной, они будут выполняться последовательно, почему вы используете блокировку выполнения? Возникли проблемы с приостановкой функции? И то же предложение, что и в IR42, для процесса блокировки рассмотрите возможность использования диспетчеров. Ввод-вывод (в противном случае диспетчеры. По умолчанию для задач, управляемых процессором).

5. callAPI вызывается из не зависшего метода. Я действительно в конечном итоге использовал диспетчеров. По умолчанию, который сработал, поэтому, если @IR42 захочет дать ответ, я сделаю это выбранным ответом.

Ответ №1:

Вам нужно указать диспетчер, отличный runBlocking от однопоточного диспетчера по умолчанию, иначе ничего не сможет выполняться параллельно.

Ваш код также может быть немного изменен для ясности / краткости.

 fun callAPI(idList: Collection<String>): List<String> = runBlocking(Dispatchers.IO) {
    idList.map {
        async { timeConsumingMethod(it) }
    }.awaitAll()
}
 

Если вы работаете с пользовательским интерфейсом, который не хотите замораживать во время операции, вам следует подумать о том, чтобы сделать эту функцию приостановленной и реагировать на результаты, когда они будут готовы, а не использовать runBlocking .