Skip to content

Instantly share code, notes, and snippets.

@sDevPrem
Created October 21, 2025 06:15
Show Gist options
  • Select an option

  • Save sDevPrem/de7869da2c30b481de0d2b1ab3141610 to your computer and use it in GitHub Desktop.

Select an option

Save sDevPrem/de7869da2c30b481de0d2b1ab3141610 to your computer and use it in GitHub Desktop.
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit
import kotlinx.coroutines.withContext
import kotlin.system.measureTimeMillis
fun main() = runBlocking {
limitedParallelismDownloads()
}
fun downloadImage(id: Int): String {
println("downloading image id $id")
Thread.sleep(2_000) //blocking call, will block the thread current until image is downloaded
return "Image-$id"
}
suspend fun suspendDownloadImage(id: Int): String = withContext(Dispatchers.IO) {
println("downloading image id $id")
Thread.sleep(2_000) //blocking call, will block the thread current until image is downloaded
return@withContext "Image-$id"
}
suspend fun suspendDownloadImage2(id: Int): String {
println("downloading image id $id")
delay(2_000) //imitating api call
return "Image-$id"
}
suspend fun uncontrolledDownloads() = coroutineScope {
val time = measureTimeMillis {
(1..10).map {
async(Dispatchers.IO) {
downloadImage(it)
println("downloaded image id $it")
}
}.awaitAll()
}
println("Downloaded all images in $time ms")
}
suspend fun limitedParallelismDownloads() = coroutineScope {
val limitedIO = Dispatchers.IO.limitedParallelism(2)
val time = measureTimeMillis {
(1..10).map {
async(limitedIO) {
suspendDownloadImage2(it)
println("downloaded image id $it")
}
}.awaitAll()
}
println("Downloaded all images (limitedParallelism) in $time ms")
}
//since it will run on the caller dispatcher which will be Main dispatcher in most cases and that dispatcher has
//only one thread so we can't parallize task here. So using Dispatchers.IO as the parent
suspend fun semaphoreDownloads() = withContext(Dispatchers.IO) {
val semaphore = Semaphore(2)
val time = measureTimeMillis {
(1..10).map {
async(Dispatchers.IO) {
semaphore.withPermit {
suspendDownloadImage(it)
println("downloaded image id $it")
}
}
}.awaitAll()
}
println("Downloaded all images (Semaphore) in $time ms")
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment