kotlin Coroutine multiple launch - kotlin

How to make multiple launch like multiple thread in kotlin
I want to make that first second are working at the same time forever!!
Like this code...
runBlocking {
// first
launch{
first()
}
// second
launch{
second()
}
}
suspend fun first(){
// do something
delay(1000L)
// Recursive call
first()
}
suspend fun second(){
// do something
delay(1000L)
// Recursive call
second()
}

Your example code would work already, if it is the only running code in your application. If you need those two methods running in parallel to your application, wrap them in GlobalScope.launch:
GlobalScope.launch {
launch { first() }
launch { second() }
}
This will run forever until canceled and/or an exception inside is thrown. If you don't require too many resources inside a coroutine and release them properly when used, you should never have a problem with StackOverFlow.
In addition to recursive code: try to make a loop instead as it is suggested in the comments.

You can implement infinite execution with cycles
runBlocking {
launch { while(true) first() }
launch { while(true) second() }
}
suspend fun first(){
// do something
delay(1000L)
}
suspend fun second(){
// do something
delay(1000L)
}

Related

Kotlin async function not run in parallel

I have a kotlin function just as following, And I expected it can wrap a sync IO action into async.
suspend fun <T> runIOAsync(f:suspend () -> T): Deferred<T> = coroutineScope{
async(Dispatchers.IO) {
f()
}
}
Then I have my code in the calling side like
runBlocking {
repeat(5) {
runIOAsync {
println(it)
println(Thread.currentThread())
Thread.sleep(3000)
println("After sleep $it")
}.await()
}
}
But the actual out put is
0
Thread[DefaultDispatcher-worker-1 #coroutine#2,5,main]
After sleep 0
1
Thread[DefaultDispatcher-worker-1 #coroutine#3,5,main]
After sleep 1
2
Thread[DefaultDispatcher-worker-1 #coroutine#4,5,main]
After sleep 2
3
Thread[DefaultDispatcher-worker-1 #coroutine#5,5,main]
After sleep 3
4
Thread[DefaultDispatcher-worker-1 #coroutine#6,5,main]
After sleep 4
Which seems all tasks from my function are executed serially. Any one can please help to give an explanation
Let's put aside runIOAsync for the moment.
You're using await() right after calling async(), which means that you're effectively waiting for the end of your async execution before executing the next one.
Instead, start all tasks first and then await all of them. For instance you can use awaitAll:
runBlocking {
List(5) {
async(Dispatchers.IO) {
println(it)
println(Thread.currentThread())
Thread.sleep(3000)
println("After sleep $it")
}
}.awaitAll()
}
Also, the way you're encapsulating the scope in runIOAsync is wrong, you will be waiting for the end of the async execution even without calling await() (coroutineScope is a suspending function that waits for all its child coroutines before resuming).
Instead, use coroutineScope to define the boundary of your coroutines executions, and you don't even have to await them. Since you don't need to get values from this code, you can also use launch instead of async here:
coroutineScope {
repeat(5) {
launch(Dispatchers.IO) {
println(it)
println(Thread.currentThread())
Thread.sleep(3000)
println("After sleep $it")
}
}
}
Declaring a suspend function returning a Deferred should be a red flag, and is quite confusing from an API standpoint: if you suspend it means you wait, if you return Deferred it means you don't wait (you immediately return a handle to some running computation). A function that does both would be quite weird.
If what you want is to make suspending code from IO-bound code, you can use instead the existing withContext function:
// this suspends until the code inside is done
withContext(Dispatchers.IO) {
// run some blocking IO code
}
However, note that this is independent from defining concurrent code. If you want to run multiple things concurrently, even with suspend functions, you'll need coroutine builders such as async or launch like in the above code.

Differences between two coroutine launch in kotlin

What's the difference between CoroutineScope(dispatchers).launch{} and coroutineScope{ launch{}}?
Say I have the code below:
(you can go to Kotlin playground to run this snippet https://pl.kotl.in/U4eDY4uJt)
suspend fun perform(invokeAfterDelay: suspend () -> Unit) {
// not printing
CoroutineScope(Dispatchers.Default).launch {
delay(1000)
invokeAfterDelay()
}
// will print
coroutineScope {
launch {
delay(1000)
invokeAfterDelay()
}
}
}
fun printSomething() {
println("Counter")
}
fun main() {
runBlocking {
perform {
printSomething()
}
}
}
And as the comment stated, when using CoroutineScope().launch it won't invoke the print, however when using the other way, the code behaves as intended.
What's the difference?
Thanks.
Further question
New findings.
if I leave the perform function like this (without commenting out one of the coroutines)
suspend fun perform(invokeAfterDelay: suspend () -> Unit) {
CoroutineScope(Dispatchers.Default).launch {
delay(1000)
invokeAfterDelay()
}
coroutineScope {
launch {
delay(1000)
invokeAfterDelay()
}
}
}
then both of these coroutines will be executed 🤔Why?
CoroutineScope().launch {} and coroutineScope { launch{} } have almost nothing in common. The former just sets up an ad-hoc scope for launch to run against, completing immediately, and the latter is a suspendable function that ensures that all coroutines launched within it complete before it returns.
The snippet under your "Further question" is identical to the original one except for the deleted comments.
Whether or not the first coroutine prints anything is up to non-deterministic behavior: while perform is spending time within coroutineScope, awaiting for the completion of the inner launched coroutine, the first one may or may not complete itself. They have the same delay.

How to execute a blocking coroutine call in kotlin and specify the thread

Is it possible to execute a blocking coroutine call (one that returns a value) while also providing the thread to execute the call on (I don't want to use the main thread, which is the default)?
I suppose you are looking for async(context):
import kotlinx.coroutines.*
fun someCalc(): Int {
println(Thread.currentThread().name) // Prints different thread
Thread.sleep(500L)
return 42
}
fun main() {
val result = runBlocking {
val deferred = async(Dispatchers.Default) {
someCalc()
}
deferred.await()
}
println(result)
}
You can also use newSingleThreadContext() to create a context confined to a single thread and use it instead of Dispatchers.Default
EDIT: As #Rene said, there is a better solution:
val result = runBlocking {
withContext(Dispatchers.Default) {
someCalc()
}
}
If you just have a thread that's already running, and you have no control over the code it runs, then there is nothing you can do about it. The thread must be running a top-level event loop so you can inject the code to run from the outside.
If, by any chance, you have this kind of control, or you can decide which Runnable the thread will run to begin with, here's some pretty hacky code that manages to set up an event loop and submit a coroutine to it:
val myContextFuture = CompletableFuture<CoroutineContext>()
thread(name = "my-thread") {
runBlocking {
myContextFuture.complete(coroutineContext)
coroutineContext[Job]!!.join()
}
}
val myContext = myContextFuture.get()
Here's how you would run a coroutine on myContext:
val result = withContext(myContext) {
println("Running on thread ${currentThread().name}")
3
}
println("Result of the coroutine: $result")
I wouldn't recommend using this kind of code in production.

Launching coroutines from a suspended function

Given we have a suspending function but this is not a CoroutineScope, how can we launch other coroutines such that those are associated with the current scope of whatever runs this suspending function?
Every suspendable function has access to the global variable coroutineContext which you can trivially wrap in CoroutineScope, but that is not its intended purpose. It's there so you can check at any point whether your coroutine was cancelled, reach the debug info like the job name, etc.
In the words of Roman Elizarov in his recent Medium post:
suspend fun doNotDoThis() {
CoroutineScope(coroutineContext).launch {
println("I'm confused")
}
}
Do not do this!
A suspendable function should not fire off concurrent work that may go on after it returns. It should only use concurrency to achieve parallel decomposition of a task, and that means it will wait for all the child coroutines to complete.
You should decide to either use a plain function that is the receiver of CoroutineScope (signaling the intention to launch concurrent work) or use a suspendable function that awaits on the completion of all the work it initiated.
So, if you want parallel decomposition, then use a coroutineScope or, possibly a supervisorScope block:
coroutineScope {
launch {
// ... task to run in the background
}
// ... more work while the launched task runs in parallel
}
// All work done by the time we reach this line
coroutineScope is a suspendable function and it won't complete until all the coroutines it launched complete.
You can create an extension function on CoroutineScope or function with CoroutineScope as a parameter:
fun CoroutineScope.doThis() {
launch { ... }
}
fun doThatIn(scope: CoroutineScope) {
scope.launch { ... }
}
Also you can use coroutineScope or supervisorScope, depending on your needs:
suspend fun someFun() = coroutineScope {
launch { ... }
}
suspend fun someFun() = supervisorScope {
launch { ... }
}
You could just use withContext() or coroutineScope() for launching another coroutine:
withContext(coroutineContext) {
launch { ... }
}
While the second would override the Job of the context, but reuse the context:
coroutineScope {
launch { ... }
}

Kotlin Coroutines - How to block to await/join all jobs?

I am new to Kotlin/Coroutines, so hopefully I am just missing something/don't fully understand how to structure my code for the problem I am trying to solve.
Essentially, I am taking a list of strings, and for each item in the list I want to send it to another method to do work (make a network call and return data based on the response). (Edit:) I want all calls to launch concurrently, and block until all calls are done/the response is acted on, and then return a new list with the info of each response.
I probably don't yet fully understand when to use launch/async, but I've tried to following with both launch (with joinAll), and async (with await).
fun processData(lstInputs: List<String>): List<response> {
val lstOfReturnData = mutableListOf<response>()
runBlocking {
withContext(Dispatchers.IO) {
val jobs = List(lstInputs.size) {
launch {
lstOfReturnData.add(networkCallToGetData(lstInputs[it]))
}
}
jobs.joinAll()
}
}
return lstofReturnData
What I am expecting to happen, is if my lstInputs is a size of 120, when all jobs are joined, my lstOfReturnData should also have a size of 120.
What actually is happening is inconsitent results. I'll run it once, and I get 118 in my final list, run it again, it's 120, run it again, it's 117, etc. In the networkCallToGetData() method, I am handling any exceptions, to at least return something for every request, regardless if the network call fails.
Can anybody help explain why I am getting inconsistent results, and what I need to do to ensure I am blocking appropriately and all jobs are being joined before moving on?
mutableListOf() creates an ArrayList, which is not thread-safe.
Try using ConcurrentLinkedQueue instead.
Also, do you use the stable version of Kotlin/Kotlinx.coroutine (not the old experimental one)? In the stable version, with the introduction of structured concurrency, there is no need to write jobs.joinAll anymore. launch is an extesion function of runBlocking which will launch new coroutines in the scope of the runBlocking and the runBlocking scope will automatically wait for all the launched jobs to finsish. So the code above can be shorten to
val lstOfReturnData = ConcurrentLinkedQueue<response>()
runBlocking {
lstInputs.forEach {
launch(Dispatches.IO) {
lstOfReturnData.add(networkCallToGetData(it))
}
}
}
return lstOfReturnData
runBlocking blocks current thread interruptibly until its completion. I guess it's not what you want. If I think wrong and you want to block the current thread than you can get rid of coroutine and just make network call in the current thread:
val lstOfReturnData = mutableListOf<response>()
lstInputs.forEach {
lstOfReturnData.add(networkCallToGetData(it))
}
But if it is not your intent you can do the following:
class Presenter(private val uiContext: CoroutineContext = Dispatchers.Main)
: CoroutineScope {
// creating local scope for coroutines
private var job: Job = Job()
override val coroutineContext: CoroutineContext
get() = uiContext + job
// call this to cancel job when you don't need it anymore
fun detach() {
job.cancel()
}
fun processData(lstInputs: List<String>) {
launch {
val deferredList = lstInputs.map {
async(Dispatchers.IO) { networkCallToGetData(it) } // runs in parallel in background thread
}
val lstOfReturnData = deferredList.awaitAll() // waiting while all requests are finished without blocking the current thread
// use lstOfReturnData in Main Thread, e.g. update UI
}
}
}
Runblocking should mean you don't have to call join.
Launching a coroutine from inside a runblocking scope should do this for you.
Have you tried just:
fun processData(lstInputs: List<String>): List<response> {
val lstOfReturnData = mutableListOf<response>()
runBlocking {
lstInputs.forEach {
launch(Dispatchers.IO) {
lstOfReturnData.add(networkCallToGetData(it))
}
}
}
return lstofReturnData