0%
August 27, 2025

Multithreading with Semaphore

kotlin

spring

For buffered channel approach the reader may refer to this article. This time we dicuss another native API from kotlin called Semaphore.

import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Semaphore
import kotlinx.coroutines.sync.withPermit


class SomeConcurrenTask(
    private val transactionTemplate: TransactionTemplate,
) {
    // divide tasks into batches with each being of size at most 20
    val taskIdsBatches = taskIds.chunked(20)
    // concurrnet limit to 10
    val semaphore = Semaphore(10)

    runBlocking {
        val deferredResults = taskIdsBatches.mapIndexed { batchIndex, taskIdsBatch ->
            async(Dispatchers.IO) {
                semaphore.withPermit {
                    println("Processing batch $batchIndex/${taskIdsBatches.size}")
                    transactionTemplate.execute {
                        someTransaction(taskIdsBatch)
                    }
                }
            }
        }

        println("Waiting for everything to finish ...")
        deferredResults.awaitAll()
        println("Finished!")
    }
}