Your first coroutine

                  import kotlinx.coroutines.*
​
fun main() {
    GlobalScope.launch { // launch a 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
}
                
                    import kotlinx.coroutines.*
​
func main() {
    GlobalScope.launch { // launch a new coroutine in background and continue
        delay(1000L) // non-blocking delay for 1 second (default time unit is ms)
        print("World!") // print after delay
    }
    print("Hello,") // main thread continues while coroutine is delayed
    Thread.sleep(2000L) // block main thread for 2 seconds to keep JVM alive
}
                  

Bridging blocking and non-blocking worlds

                  import kotlinx.coroutines.*
​
fun main() { 
    GlobalScope.launch { // launch a new coroutine in background and continue
        delay(1000L)
        println("World!")
    }
    println("Hello,") // main thread continues here immediately
    runBlocking {     // but this expression blocks the main thread
        delay(2000L)  // ... while we delay for 2 seconds to keep JVM alive
    } 
}
                
                    import kotlinx.coroutines.*
​
func main() { 
    GlobalScope.launch { // launch a new coroutine in background and continue
        delay(1000L)
        print("World!")
    }
    print("Hello,") // main thread continues here immediately
    runBlocking {     // but this expression blocks the main thread
        delay(2000L)  // ... while we delay for 2 seconds to keep JVM alive
    } 
}
                  
                  import kotlinx.coroutines.*
​
fun main() = runBlocking<Unit> { // start main coroutine
    GlobalScope.launch { // launch a new coroutine in background and continue
        delay(1000L)
        println("World!")
    }
    println("Hello,") // main coroutine continues here immediately
    delay(2000L)      // delaying for 2 seconds to keep JVM alive
}
                
                    import kotlinx.coroutines.*
​
func main() = runBlocking<Unit> { // start main coroutine
    GlobalScope.launch { // launch a new coroutine in background and continue
        delay(1000L)
        print("World!")
    }
    print("Hello,") // main coroutine continues here immediately
    delay(2000L)      // delaying for 2 seconds to keep JVM alive
}
                  
                  class MyTest {
    @Test
    fun testMySuspendingFunction() = runBlocking<Unit> {
        // here we can use suspending functions using any assertion style that we like
    }
}
                
                    class MyTest {
    @Test
    func testMySuspendingFunction() = runBlocking<Unit> {
        // here we can use suspending functions using any assertion style that we like
    }
}
                  

Waiting for a job

                  val job = GlobalScope.launch { // launch a new coroutine and keep a reference to its Job
    delay(1000L)
    println("World!")
}
println("Hello,")
job.join() // wait until child coroutine completes
                
                    let job = GlobalScope.launch { // launch a new coroutine and keep a reference to its Job
    delay(1000L)
    print("World!")
}
print("Hello,")
job.join() // wait until child coroutine completes
                  

Structured concurrency

                  import kotlinx.coroutines.*
​
fun main() = runBlocking { // this: CoroutineScope
    launch { // launch a new coroutine in the scope of runBlocking
        delay(1000L)
        println("World!")
    }
    println("Hello,")
}
                
                    import kotlinx.coroutines.*
​
func main() = runBlocking { // this: CoroutineScope
    launch { // launch a new coroutine in the scope of runBlocking
        delay(1000L)
        print("World!")
    }
    print("Hello,")
}
                  

Scope builder

                  import kotlinx.coroutines.*
​
fun main() = runBlocking { // this: CoroutineScope
    launch { 
        delay(200L)
        println("Task from runBlocking")
    }
    
    coroutineScope { // Creates a coroutine scope
        launch {
            delay(500L) 
            println("Task from nested launch")
        }
    
        delay(100L)
        println("Task from coroutine scope") // This line will be printed before the nested launch
    }
    
    println("Coroutine scope is over") // This line is not printed until the nested launch completes
}
                
                    import kotlinx.coroutines.*
​
func main() = runBlocking { // this: CoroutineScope
    launch { 
        delay(200L)
        print("Task from runBlocking")
    }
    
    coroutineScope { // Creates a coroutine scope
        launch {
            delay(500L) 
            print("Task from nested launch")
        }
    
        delay(100L)
        print("Task from coroutine scope") // This line will be printed before the nested launch
    }
    
    print("Coroutine scope is over") // This line is not printed until the nested launch completes
}
                  

Extract function refactoring

                  import kotlinx.coroutines.*
​
fun main() = runBlocking {
    launch { doWorld() }
    println("Hello,")
}
​
// this is your first suspending function
suspend fun doWorld() {
    delay(1000L)
    println("World!")
}
                
                    import kotlinx.coroutines.*
​
func main() = runBlocking {
    launch { doWorld() }
    print("Hello,")
}
​
// this is your first suspending function
suspend func doWorld() {
    delay(1000L)
    print("World!")
}
                  

Coroutines ARE light-weight

                  import kotlinx.coroutines.*
​
fun main() = runBlocking {
    repeat(100_000) { // launch a lot of coroutines
        launch {
            delay(5000L)
            print(".")
        }
    }
}
                
                    import kotlinx.coroutines.*
​
func main() = runBlocking {
    repeat(100_000) { // launch a lot of coroutines
        launch {
            delay(5000L)
            print(".")
        }
    }
}
                  

Global coroutines are like daemon threads

                  GlobalScope.launch {
    repeat(1000) { i ->
        println("I'm sleeping $i ...")
        delay(500L)
    }
}
delay(1300L) // just quit after delay
                
                    GlobalScope.launch {
    repeat(1000) { i ->
        print("I'm sleeping $i ...")
        delay(500L)
    }
}
delay(1300L) // just quit after delay