Many coroutines can share a smaller number of threads. When a suspending operation pauses, the coroutine retains the information needed to resume rather than reserving a dedicated OS thread for the entire wait.
This helps workloads with many waits, but running code still needs a thread. A CPU-heavy loop does not become cheap because it sits inside launch.
Imagine downloading thumbnails for a large course library. Starting a coroutine for every thumbnail can retain thousands of request objects and compete for connections. Put a deliberate limit around the scarce resource.
val permits = Semaphore(4)
suspend fun fetchThumbnail(id: String): ByteArray =
permits.withPermit {
imageApi.download(id)
}
This fragment uses kotlinx.coroutines.sync.Semaphore and withPermit. It limits in-flight downloads using this shared semaphore. It does not limit the number of waiting coroutines or the memory needed to retain all downloaded images; a large input may need a bounded work queue and incremental consumption.
How would you choose the limit? Measure latency, memory, server constraints, and cancellation behavior under realistic load. More concurrency can reduce throughput when the bottleneck is saturated. Avoid claiming a universal safe coroutine count.
Mark this when you can explain the answer in your own words.
Help fellow developers prepare for interviews
Sharing helps the Android community grow ๐