TGViewer
Kotlin Kotlin @kotlin_lib · 2.05K subscribers
Post #704 842
🛑 Как задушить свое приложение, используя Dispatchers.IO

Мы привыкли думать, что Dispatchers.IO - это бездонная бочка. Закинул туда сетевой запрос или чтение файла, и корутины сами всё разрулят.

Но у Dispatchers.IO есть жесткий лимит - 64 потока (или количество ядер процессора, если их больше).

Сценарий катастрофы:
Вам нужно скачать 100 картинок или сделать батч-запросы к очень мееееедленному стороннему API. Вы запускаете 100 корутин на IO.
Первые 64 запроса занимают все доступные потоки пула и зависают в ожидании ответа от сервера (I/O block).

В этот момент пользователь нажимает кнопку "Сохранить профиль". Метод сохранения идет в локальную БД (Room/Realm), которая тоже использует Dispatchers.IO.
Результат: Запрос в БД не выполняется. Он встает в очередь и ждет, пока хотя бы одна из 64 картинок скачается и освободит системный поток. Пользователь видит бесконечный лоадер. Приложение кажется "зависшим", хотя ANR нет.

🛠 Как это лечат Джуны?
Создают свой пул: Executors.newFixedThreadPool(100).asCoroutineDispatcher().
Почему это плохо: Вы плодите тяжеловесные системные потоки в обход общего механизма корутин. Это жрет память и ломает шаринг ресурсов.

👑 Как это лечат Сеньоры?

Используют limitedParallelism. У этого метода есть две суперсилы.

Суперсила 1: Расширение лимита


// Да, этот вызов легально расширяет лимит для конкретной задачи!
val ImageDownloadDispatcher = Dispatchers.IO.limitedParallelism(100)



Документация гласит: вызов limitedParallelism на Dispatchers.IO создает независимый пул, который может превышать глобальный лимит в 64 потока, при этом используя общий elastic thread pool под капотом. Картинки будут качаться в 100 потоков, не блокируя остальные задачи на дефолтном IO.

Суперсила 2: Изоляция узких бутылочных горлышек (Bottlenecks)
Допустим, у вашей базы данных (SQLite/Room) пул коннектов равен 4.
Если вы отправите 20 корутин писать в БД на Dispatchers.IO, 4 будут писать, а 16 - тупо заблокируют потоки IO, ожидая свободного коннекта к БД.

Делаем так:


val DbDispatcher = Dispatchers.IO.limitedParallelism(4)



Теперь, если вы запустите 20 корутин на DbDispatcher, только 4 потока будут заняты. Остальные 16 корутин будут приостановлены (suspended), не блокируя системные потоки. Ваш основной IO диспетчер останется свободным для сети и файлов.

Чек-лист:
Выделяйте кастомные диспетчеры через limitedParallelism для:

1. Массовых долгих сетевых операций.
2. Работы с БД (по размеру connection pool).
3. Работы с Legacy SDK, которые не поддерживают асинхронность.

Кто из вас уже сталкивался с Thread Starvation в корутинах? Искали долго? 👇

✍️ @kotlin_lib
  • 👍 6
More from @kotlin_lib
  1. Aug 26, 2026🚧 Ваш Mutex тормозит корутины. Как перестать лочить и начать жить Вы пишете многопоточный…
  2. Jul 25, 2026🚀 Подборка полезных IT каналов в Max Системное администрирование, DevOps 📌 https://max.r…
  3. Jul 1, 2026🌪 Ваша дата в опасности: flatMapConcat vs Merge vs Latest Вам нужно взять поток ID-шников…
  4. Jun 24, 2026🤖 Android-приложение — это не только красивый экран. За ним стоят работа с внешним API, з…
  5. Jun 23, 2026🔮 Убийца бойлерплейта: Встречайте Context Parameters (Kotlin 2.x) Мы так привыкли к Depen…
  6. Jun 3, 2026Яндекс обновил Yandex Mobile Ads SDK для монетизации мобильных приложений — и это интересн…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →