Какие диспетчеры корутин существуют и для чего они нужны
Что проверяют
Понимаете ли вы, что диспетчер это не поток, а политика назначения корутины на пул потоков, и выбираете ли его осознанно, а не «на всякий случай IO». Следом обычно спрашивают, кто должен переключать поток: вызывающий код или сама suspend-функция.
Как отвечать
Перечислите четыре штатных диспетчера сразу с их свойствами:
Dispatchers.Main: главный поток Android, только работа с UI; у него есть вариантMain.immediate, который не ставит задачу в очередьLooper, если вы уже на главном потоке;Dispatchers.IO: блокирующие операции, файлы, сеть, SQLite; по умолчанию допускает до 64 параллельных задач или столько, сколько ядер, если ядер больше;Dispatchers.Default: вычисления, парсинг, сортировка больших коллекций; размер пула равен числу ядер, но не меньше двух;Dispatchers.Unconfined: поток не переключает вовсе, продолжение выполняется там, где завершилась suspend-точка. В продакшене почти не нужен, его место в тестах.
Дальше две вещи, которые отличают знающего кандидата. Первая: IO и Default делят общий пул потоков, поэтому withContext(Dispatchers.IO) из корутины на Default меняет лимит параллелизма, а не создаёт новый поток, и стоит дёшево. Вторая: main-safety это ответственность библиотеки. Room, Retrofit и DataStore сами уходят с главного потока, оборачивать их вызовы в withContext не нужно.
Полезно упомянуть limitedParallelism(n) для своей квоты (например, один поток на запись в файл) и тестируемость: диспетчер передаётся в конструктор репозитория, в тестах подменяется на StandardTestDispatcher, а главный на Dispatchers.setMain.
Где спотыкаются
Отправляют на IO тяжёлые вычисления. Шестьдесят четыре параллельные CPU-задачи на восьми ядрах не ускорят ничего, зато отберут потоки у настоящего ввода-вывода.
Говорят, что Dispatchers.IO защищает от блокировки. Он лишь уводит блокировку с главного потока: займите все слоты Thread.sleep или сокетом без таймаута, и следующий сетевой запрос встанет в очередь.
Жёстко зашивают Dispatchers.IO в тело репозитория. Такой код в тесте всегда уезжает на реальный пул, runTest перестаёт управлять виртуальным временем, и тесты плавают.