Какие контексты и диспетчеры есть у корутин в Kotlin и для чего они нужны
Что проверяют
Понимаете ли вы, из чего состоит контекст, и знаете ли назначение каждого диспетчера.
Как отвечать
Контекст корутины это набор элементов, складываемых оператором сложения. Основных четыре:
Job: жизненный цикл и отмена. Через него работает структурная конкурентность, отмена родителя отменяет детей;CoroutineDispatcher: на каком потоке выполняться;CoroutineName: имя для отладки, видно в журнале и в дампе;CoroutineExceptionHandler: обработчик необработанных исключений на уровне области.
Диспетчеры:
Dispatchers.Main: главный поток, только он трогает интерфейс. Вариант с немедленным выполнением не переключает контекст, если вы уже на главном потоке, что убирает лишний кадр задержки;Dispatchers.IO: пул для блокирующих операций: файлы, сеть через синхронные библиотеки, база. По умолчанию расширяется до 64 потоков, потому что они в основном ждут;Dispatchers.Default: пул размером по числу ядер для вычислений: разбор больших ответов, сортировка, обработка изображений;Dispatchers.Unconfined: не переключает поток, продолжает на том, где освободилось ожидание. В прикладном коде почти не нужен.
Важная деталь: два основных пула делят общие потоки, поэтому переключение между ними дешёвое и не создаёт новых потоков.
Смена контекста делается функцией переключения, которая возвращает результат и возвращает выполнение обратно:
val data = withContext(Dispatchers.IO) { repository.load() }Для ограничения одновременности есть отдельный механизм: он выделяет из пула не больше заданного числа потоков, что удобно, когда внешний сервис не выдерживает много параллельных запросов.
В тестах диспетчеры подменяются специальными тестовыми, а главный заменяется явно, иначе тест упадёт из-за отсутствия петли главного потока.
Где спотыкаются
Отправляют вычисления в пул для ввода-вывода, вытесняя оттуда реальные ожидания.
Используют launch(Dispatchers.Main) и делают в нём тяжёлую работу.
Не подменяют главный диспетчер в тестах.
Считают, что смена диспетчера создаёт новый поток каждый раз.