What is a function ?
A sequence of instructions that takes inputs and gives us outputs
fun makeASandwich(): Sandwich{
val bread = Bread(seed = oat)
val sauce = "harissa" + "mayo"
return Sandwich(bread, sauce, "beef")
}
fun goToRestaurant(): Boolean?{
throw YouAreBrokeDude()
return null
}
fun eat(){
try{
goToRestaurant()
}
catch(error: YouAreBrokeDude){
makeASandwich()
}
}
eat()
A thread describe in which context this sequence of instructions should be executed
//Thread 1
println("Hello world")
var x = 3
x *= x
println("The result is $x")
//Thread 2
println("Hello world from another thread")
var x = 5
x *= x
println("The result is $x from the other thread")
doSomething()
callAPI() //Take time
doSomethingElse()
Because it's costly, hard to maintain and consume your hardware resources
fun doSomething(){
//...
}
suspend fun doSomething(){
//...
}
suspend functions can only be called from coroutines or other functions with suspension points. They cannot be called by normal code
launch {
doSomething()
}
suspend fun doSomething(){
//...
}
launch {
doSomething()
}
fun doSomething(){
//...
}
doSomething()
fun main(args: Array<String>) {
launch { // launch new coroutine in background and continue
delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
println("World!") // print after delay
}
println("Hello,") // main thread continues while coroutine is delayed
Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}
fun main(args: Array<String>) = runBlocking<Unit> {
val time = measureTimeMillis {
val one = async { doSomethingUsefulOne() }
val two = async { doSomethingUsefulTwo() }
println("The answer is ${one.await() + two.await()}")
}
println("Completed in $time ms")
}
The main difference between async and launch is that launch is used for starting a computation that isn't expected to return a specific result. launch returns Job, which represents the coroutine. It is possible to wait until it completes by calling Job.join() but rather use async in that case.
suspend fun demo() : Any = TODO()
fun main(args: Array<String>) {
// demo() // this alone wouldn't compile... Error:() Kotlin: Suspend function 'demo' should be called only from a coroutine or another suspend function
// whereas the following works as intended:
runBlocking {
demo()
} // it also waits until demo()-call is finished which wouldn't happen if you use launch
}
runBlocking is used as a bridge between regular and suspend functions, between blocking and non-blocking worlds. It works as an adaptor for starting the top-level main coroutine and is intended primarily to be used in main functions and in tests.
PLEASE AVOID IT WHEN YOU ARE UNSURE
async{ ... }
async(Dispatchers.DEFAULT){ ... }
Use dispatcher from the outer scope
Use a shared pool on the JVM
Every coroutine in Kotlin has a context that is represented by an instance of CoroutineContext interface. A context is a set of elements and current coroutine context is available via coroutineContext property:
fun main() = runBlocking<Unit> {
println("My context is: $coroutineContext")
}
// My context is: [CoroutineId(1), "coroutine#1":BlockingCoroutine{Active}@5b80350b, BlockingEventLoop@5d6f64b1]
There is also an interface called CoroutineScope that consists of a sole property — val coroutineContext: CoroutineContext. It has nothing else but a context
public interface CoroutineScope {
/**
* The context of this scope.
* Context is encapsulated by the scope and used for implementation of coroutine builders that are extensions on the scope.
* Accessing this property in general code is not recommended for any purposes except accessing the [Job] instance for advanced usages.
*
* By convention, should contain an instance of a [job][Job] to enforce structured concurrency.
*/
public val coroutineContext: CoroutineContext
}
package coroutines
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
fun main() {
println("🍔")
runBlocking() {
launch {
delay(1000)
println("🍕")
}
launch {
delay(500)
println("🍰")
}
}
println("🍦")
}
package coroutines
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.GlobalScope
fun main(){
println("🍔")
runBlocking() {
GlobalScope.launch {
delay(1000)
println("🍕")
}
GlobalScope.launch {
delay(500)
println("🍰")
}
}
println("🍦")
}