Что такое Dispatcher в корутинах Kotlin и какие они бывают
Что проверяют
Знаете ли вы четыре стандартных диспетчера и понимаете ли разницу IO и Default. Именно на ней чаще всего ошибаются.
Как отвечать
Диспетчер это часть контекста корутины, определяющая, на каком потоке она выполняется.
- Dispatchers.Main: главный поток, всё, что касается интерфейса. Вариант
Main.immediateне переключает контекст, если он уже главный; - Dispatchers.Default: пул по числу ядер (минимум два). Для вычислений: разбор, сортировка, обработка данных;
- Dispatchers.IO: пул до 64 потоков, рассчитан на ожидание. Сеть, файлы, блокирующие драйверы. Потоки делит с
Default, но лимит свой; - Dispatchers.Unconfined: выполняется на вызывающем потоке до первой приостановки. В обычном коде не нужен, применяется в тестах.
Разница IO и Default принципиальная: первый допускает блокировку потока, второй нет. Тяжёлый расчёт на IO занимает поток, предназначенный для ожидания; блокирующий вызов на Default съедает ядро из маленького пула и подвешивает остальные вычисления.
Переключение делается через withContext(Dispatchers.IO) { ... }, причём принято, чтобы приостанавливаемая функция выбирала диспетчер сама, а вызывающий об этом не думал.
Для тестов есть StandardTestDispatcher и UnconfinedTestDispatcher вместе с runTest, чтобы выполнение было предсказуемым.
Где спотыкаются
Считают IO бесконечным и запускают на нём сотни блокирующих задач.
Меняют местами IO и Default.
Обновляют интерфейс не с Main и получают падение.
Заставляют вызывающего оборачивать вызовы в withContext, вместо того чтобы сделать это внутри функции.