Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Limiting the maximum number of coroutines that can run in a scope

I am translating our current application from Java to Kotlin and I came upon this problem.

The java implementation used to use threads to transfer data from the server.

It would create about 100 different threads that would request data, but from what I have seen no more than 4 would run at a time, the others would wait for a thread to finish before starting.

When translating it to Kotlin I used Coroutines

This creates a problem because apparently the server can't handle 100 requests actually being sent.

All coroutines are launched in the same scope , so it's something like this:

//this is a custom scope that launches on Dispatchers.IO + a job that I can use to cancel everything
transferScope.launch {
     //loadData is a suspending function that returns true/false 
     val futures = mDownloadJobs.map{ async { it.loadData() } }
     val responses = futures.awaitAll()
     //check that everything in responses is true etc....
}

Is there a way to make the specific transferScope to allow only up to 5 coroutines at a time and then when one finishes let a different one run? (I do not care about the order)

If it can't be done through the scope, is there a different way this can be achieved?

like image 496
Cruces Avatar asked Oct 17 '19 08:10

Cruces


People also ask

How many coroutines can run at a given time?

A coroutine is executed inside a thread. One thread can have many coroutines inside it, but as already mentioned, only one instruction can be executed in a thread at a given time.

How many scopes are there in coroutines?

There are basically 3 scopes in Kotlin coroutines: Global Scope. LifeCycle Scope. ViewModel Scope.

What is run blocking in coroutines?

Definition of runBlocking() functionRuns a new coroutine and blocks the current thread interruptible until its completion. This function should not be used from a coroutine. It is designed to bridge regular blocking code to libraries that are written in suspending style, to be used in main functions and in tests.

When should you not use coroutines?

Answer: a. You should not use them for any foreground task.


1 Answers

Require each coroutine to acquire a Kotlin Semaphore permit from a total of 5 permits before making a request.

Something like this:

    import kotlinx.coroutines.sync.Semaphore

    val requestSemaphore = Semaphore(5)

    val futures = mDownloadJobs.map {
        async {
            // Will limit number of concurrent requests to 5
            requestSemaphore.withPermit {
                it.loadData()
            }
        }
    }

    val responses = futures.awaitAll()
like image 98
Enselic Avatar answered Nov 15 '22 08:11

Enselic