Take the following two samples of code (taken from the Kotlin documentation and from the Coroutines library README respectively):
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
delay(2000)
println("World")
}
println("Hello")
}
In Kotlin >= 1.3.0 one can mark the main() function as suspendable and use a coroutineScope directly.
import kotlinx.coroutines.*
suspend fun main() = coroutineScope {
launch {
delay(2000)
println("World")
}
println("Hello")
}
Both produce the same output:
Hello
World
Are there any functional differences between the two approaches? If yes, what are they?
runBlocking() and coroutineScope() are functionally very similar. They both pause the current execution waiting until the inner coroutine finishes. The difference is that runBlocking() is meant to be executed from a regular non-suspendable code, so it waits by blocking and coroutineScope() is used from suspendable context, so it suspends.
That difference makes them do much different things internally. runBlocking() has to first initialize the whole coroutines machinery before it could execute a suspendable lambda. coroutineScope() has access to existing coroutine context, so it only schedules the inner lambda to be executed and suspends.
Now, suspend fun main() is just a "shortcut" that Kotlin compiler provides to make it easier to initialize coroutines apps. Internally, it creates a bridge between the real main function and your suspendable main function. It generates a separate main() function, which is not suspendable and is the "real" main function. This function initializes a coroutine and uses internal runSuspend() utility to execute your suspend fun main(). This is described here: https://github.com/Kotlin/KEEP/blob/master/proposals/enhancing-main-convention.md#implementation-details-on-jvm-1
Both methods of starting a coroutine application are very similar and you can choose according to your taste. One notable difference is that runBlocking() creates a dispatcher using the current "main" thread. suspend fun main() also executes using the main thread, but it doesn't specify the dispatcher, so whenever you use e.g. coroutineScope() it will switch to Dispatchers.Default. As a result, your runBlocking() example uses single-threaded dispatcher while your coroutineScope() example uses multi-threaded Dispatchers.Default. However, this difference should not really be taken into account when choosing between both methods. We can very easily switch dispatchers at any time.
Related
Take the following two samples of code (taken from the Kotlin documentation and from the Coroutines library README respectively):
import kotlinx.coroutines.*
fun main() = runBlocking {
launch {
delay(2000)
println("World")
}
println("Hello")
}
In Kotlin >= 1.3.0 one can mark the main() function as suspendable and use a coroutineScope directly.
import kotlinx.coroutines.*
suspend fun main() = coroutineScope {
launch {
delay(2000)
println("World")
}
println("Hello")
}
Both produce the same output:
Hello
World
Are there any functional differences between the two approaches? If yes, what are they?
runBlocking() and coroutineScope() are functionally very similar. They both pause the current execution waiting until the inner coroutine finishes. The difference is that runBlocking() is meant to be executed from a regular non-suspendable code, so it waits by blocking and coroutineScope() is used from suspendable context, so it suspends.
That difference makes them do much different things internally. runBlocking() has to first initialize the whole coroutines machinery before it could execute a suspendable lambda. coroutineScope() has access to existing coroutine context, so it only schedules the inner lambda to be executed and suspends.
Now, suspend fun main() is just a "shortcut" that Kotlin compiler provides to make it easier to initialize coroutines apps. Internally, it creates a bridge between the real main function and your suspendable main function. It generates a separate main() function, which is not suspendable and is the "real" main function. This function initializes a coroutine and uses internal runSuspend() utility to execute your suspend fun main(). This is described here: https://github.com/Kotlin/KEEP/blob/master/proposals/enhancing-main-convention.md#implementation-details-on-jvm-1
Both methods of starting a coroutine application are very similar and you can choose according to your taste. One notable difference is that runBlocking() creates a dispatcher using the current "main" thread. suspend fun main() also executes using the main thread, but it doesn't specify the dispatcher, so whenever you use e.g. coroutineScope() it will switch to Dispatchers.Default. As a result, your runBlocking() example uses single-threaded dispatcher while your coroutineScope() example uses multi-threaded Dispatchers.Default. However, this difference should not really be taken into account when choosing between both methods. We can very easily switch dispatchers at any time.
I think conceptually this should work. But there is an error:
Suspend function 'dueWorkingHours' should be called only from a coroutine or another suspend function
Is Java and Kotlin parallelization not compatible? Is there a way around this?
Actually, I have the Runnable only to through it into a Handler:
handler.postDelayed(myRunnable, 100)
If there is a similar concept in Kotlin that I could use instead that would be fine too.
It’s not just a matter of Java and Kotlin parallelism being compatible or not. Even in pure Kotlin projects, you can never call suspend functions from outside a coroutine or other suspend function. There has to be some coroutine entry point for the suspend function to have a CoroutineContext, CoroutineScope, and Continuation, which are necessary ingredients for coroutines to work.
If you want to start a coroutine that does something after a delay, you use a CoroutineScope to launch a coroutine and you can call delay() as the first thing you do in that coroutine.
I'm trying to understand kotlin coroutines, I'm coming from C# and there's something I'm not understanding here in kotlin. In this scenario I'm writing a webapi using Kotlin in the Quarkus framework. From what I can tell if I label a controller (or resource) function as a suspend function quarkus will automatically launch it in a coroutine.
The issue i have is i don't know what the preferred method for suspending that coroutine is. The vast majority of examples I see on kotlin coroutines use the delay() function, which internally uses suspendCancellableCoroutine() to suspend the function. That makes sense, but i don't see a lot of example calling suspendCancellableCoroutine() explicitly. I've done some reading about the underlying code that gets generated in a suspend function, and some resources lead me to believe that by virtue of calling another suspend function i'll hit a suspend point and that will suspend my coroutine. In C# i'd usually just call await() from inside my async function to execute the long running code.
In my kotlin setup i have setup an instance of jmeter and i simulate 5 threads calling my API at the same time, while limiting my program to run on a single thread in quarkus. My API then makes a call to another API (i'll call that API, data API from now on), which could be a long running operation. For the purpose of my test my data API has a 1 second sleep in it.
Essentially:
web api controller -> web api processing -> web api calls data api through client -> data API does slow operation
I've tried calling async/await on the call to the data API, which seems to work, JMeter reports that 5 requests are all completed in roughly 1 second, and the logging i have indicates that all 5 requests are handled on a single thread. This feels clunky though. I'm already in a coroutine and now my coroutine is creating a new coroutine (async is a coroutine builder) to execute the long running function.
I've also removed the async/await and updated the call to the data API to be a suspend function as well (though this is a client generated from resteasy client). This also seems to work, but resteasy reactive could be generating something that's doing the suspend for me. I need to work with a simpler example, but in the mean time...
If i'm not using the delay() function in Kotlin, and i'm executing code in a coroutine, what is the preferred method to indicate that a section of code is potentially blocking and my coroutine should be suspended? Do i launch a new coroutine? Call suspendCancellableCoroutine()? Or something else? Probably overthinking this, but i want to make sure i understand this.
The coroutines library provides several suspend functions you can use to suspend in a coroutine or in another suspend function, among them:
withContext
delay
coroutineScope
supervisorScope
suspendCoroutine
suspendCancellableCoroutine
Job.join
Deferred.await
The typical way to convert blocking (long-running synchronous) code into something you can use in a coroutine is to wrap it in withContext(Dispatchers.Default) { } or withContext(Dispatchers.IO) { }. If it's something you use repeatedly, you can write a suspend function for it:
suspend fun foo() = withContext(Dispatchers.IO) {
blockingFoo()
}
but if it's some one-off blocking chunk of code, you can use withContext directly in a coroutine.
Note, using async { }.await() is basically never done. The compiler warns you against it. You should be using withContext instead. Calling await on a Deferred is used either when one coroutine needs a result from some other coroutine that has been passed to it, or when you're working with multiple parallel children coroutines inside a coroutineScope block.
The typical way to convert asynchronous callback-based code into a suspend function so you can use it synchronously in a coroutine is to use suspendCoroutine or suspendCancellableCoroutine. You can look up how to use those. They are pretty low level. Many libraries like Retrofit and Firebase already provide suspend functions you can use instead of the callbacks.
coroutineScope and supervisorScope are for creating a scope inside your coroutine to run multiple children coroutines in parallel and wait for them all.
I am using BufferedOutputStream
suspend fun write(byteArray: ByteArray) {
bos.write(byteArray)
}
But when I add suspend keyword I got warning:
Inappropriate blocking method call
What is the correct way to use output stream with coroutines?
OutputStream.write is a blocking function, and by convention suspend functions must never block. You can wrap it in withContext so it uses the IO dispatcher to do it appropriately. However, it is possible this won't make the warning go away because the Kotlin lint is kind of buggy about false positives for this issue.
suspend fun write(byteArray: ByteArray) = withContext(Dispatchers.IO) {
bos.write(byteArray)
}
In general if there is a truly async alternative, it better suits the coroutines model. You could find callback-based APIs and wrap them into suspend functions using suspendCoroutine or suspendCancellableCoroutine.
However, more often than not, you need to deal with actual blocking IO.
In that case, the easiest is to simply run the blocking IO on the IO dispatcher using withContext(Dispatchers.IO):
suspend fun write(byteArray: ByteArray) = withContext(Dispatchers.IO) {
bos.write(byteArray)
}
However, you have to think about which level you're using the IO dispatcher at. If this method is quite low-level, maybe you should use withContext higher in the call stack, and just keep this method non-suspend.
Is there a specific language implementation in Kotlin which differs from another language's implementation of coroutines?
What does it mean that a coroutine is like a lightweight thread?
What is the difference?
Are Kotlin coroutines actually running in parallel (concurrently)?
Even in a multi-core system, is there only one coroutine running at any given time?
Here I'm starting 100,000 coroutines. What happens behind this code?
for(i in 0..100000){
async(CommonPool){
// Run long-running operations
}
}
What does it mean that a coroutine is like a lightweight thread?
Coroutine, like a thread, represents a sequence of actions that are executed concurrently with other coroutines (threads).
What is the difference?
A thread is directly linked to the native thread in the corresponding OS (operating system) and consumes a considerable amount of resources. In particular, it consumes a lot of memory for its stack. That is why you cannot just create 100k threads. You are likely to run out of memory. Switching between threads involves OS kernel dispatcher and it is a pretty expensive operation in terms of CPU cycles consumed.
A coroutine, on the other hand, is purely a user-level language abstraction. It does not tie any native resources and, in the simplest case, uses just one relatively small object in the JVM heap. That is why it is easy to create 100k coroutines. Switching between coroutines does not involve OS kernel at all. It can be as cheap as invoking a regular function.
Are Kotlin coroutines actually running in parallel (concurrently)? Even in a multi-core system, is there only one coroutine running at any given time?
A coroutine can be either running or suspended. A suspended coroutine is not associated to any particular thread, but a running coroutine runs on some thread (using a thread is the only way to execute anything inside an OS process). Whether different coroutines all run on the same thread (a thus may use only a single CPU in a multicore system) or in different threads (and thus may use multiple CPUs) is purely in the hands of a programmer who is using coroutines.
In Kotlin, dispatching of coroutines is controlled via coroutine context. You can read more about then in the
Guide to kotlinx.coroutines
Here I'm starting 100,000 coroutines. What happens behind this code?
Assuming that you are using launch function and CommonPool context from the kotlinx.coroutines project (which is open source) you can examine their source code here:
launch is defined here https://github.com/Kotlin/kotlinx.coroutines/blob/master/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Builders.kt
CommonPool is defined here https://github.com/Kotlin/kotlinx.coroutines/blob/master/core/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/CommonPool.kt
The launch just creates new coroutine, while CommonPool dispatches coroutines to a ForkJoinPool.commonPool() which does use multiple threads and thus executes on multiple CPUs in this example.
The code that follows launch invocation in {...} is called a suspending lambda. What is it and how are suspending lambdas and functions implemented (compiled) as well as standard library functions and classes like startCoroutines, suspendCoroutine and CoroutineContext is explained in the corresponding Kotlin coroutines design document.
Since I used coroutines only on JVM, I will talk about the JVM backend. There are also Kotlin Native and Kotlin JavaScript, but these backends for Kotlin are out of my scope.
So let's start with comparing Kotlin coroutines to other languages coroutines. Basically, you should know that there are two types of coroutines: stackless and stackful. Kotlin implements stackless coroutines - it means that coroutine doesn't have its own stack, and that limiting a little bit what coroutine can do. You can read a good explanation here.
Examples:
Stackless: C#, Scala, Kotlin
Stackful: Quasar, Javaflow
What does it mean that a coroutine is like a lightweight thread?
It means that coroutine in Kotlin doesn't have its own stack, it doesn't map on a native thread, it doesn't require context switching on a processor.
What is the difference?
Thread - preemptively multitasking. (usually).
Coroutine - cooperatively multitasking.
Thread - managed by OS (usually).
Coroutine - managed by a user.
Are Kotlin coroutines actually running in parallel (concurrently)?
It depends. You can run each coroutine in its own thread, or you can run all coroutines in one thread or some fixed thread pool.
More about how coroutines execute is here.
Even in a multi-core system, is there only one coroutine running at any given time?
No, see the previous answer.
Here I'm starting 100,000 coroutines. What happens behind this code?
Actually, it depends. But assume that you write the following code:
fun main(args: Array<String>) {
for (i in 0..100000) {
async(CommonPool) {
delay(1000)
}
}
}
This code executes instantly.
Because we need to wait for results from async call.
So let's fix this:
fun main(args: Array<String>) = runBlocking {
for (i in 0..100000) {
val job = async(CommonPool) {
delay(1)
println(i)
}
job.join()
}
}
When you run this program, Kotlin will create 2 * 100000 instances of Continuation, which will take a few dozen MB of RAM, and in the console, you will see numbers from 1 to 100000.
So let’s rewrite this code in this way:
fun main(args: Array<String>) = runBlocking {
val job = async(CommonPool) {
for (i in 0..100000) {
delay(1)
println(i)
}
}
job.join()
}
What do we achieve now? Now we create only 100,001 instances of Continuation, and this is much better.
Each created Continuation will be dispatched and executed on CommonPool (which is a static instance of ForkJoinPool).