---
# System prepended metadata

title: Kotlin Coroutine 筆記

---

# Kotlin Coroutine 筆記

## runBlocking
作為blocking與Non blocking的橋樑
會等到job全部完成才離開
```kotlin=
println("outside start")

runBlocking {

    launch {
        repeat(10) {
            println("launch $it")
            delay(100)
        }
    }

    println("runBlocking completed")
}

println("outside end")
```
輸出結果:
I/System.out: outside start
I/System.out: runBlocking completed
I/System.out: launch 0
I/System.out: launch 1
I/System.out: launch 2
I/System.out: launch 3
I/System.out: launch 4
I/System.out: launch 5
I/System.out: launch 6
I/System.out: launch 7
I/System.out: launch 8
I/System.out: launch 9
I/System.out: outside end

## launch
會掛起函式等待有空才做
所謂的有空是指遇到suspend fun
而delay()跟yield()都是一種suspend fun
```kotlin=
runBlocking {

    launch {
        repeat(3){
            println("launch1 $it")
            delay(100)
        }
    }

    launch {
        repeat(3){
            println("launch2 $it")
        }
    }

    println("runBlocking completed")
}
```
輸出結果:
I/System.out: outside start
I/System.out: runBlocking completed
I/System.out: launch1 0
I/System.out: launch2 0
    launch2 1
    launch2 2
I/System.out: launch1 1
I/System.out: launch1 2
I/System.out: outside end

## suspend 
可以暫停block讓出資源,待恢復後繼續往下執行
suspend fun只能在coroutine或其他suspend fun中呼叫
```kotlin=
suspend fun suspendPrint(it:Int){
    println("suspendPrint $it")
    delay(1000)
}
```

## Deferred<T>
await()與join()類似,都會等待執行結束
await有回傳值
```kotlin=
runBlocking {

    val time = measureTimeMillis {

        val a: Deferred<Int> = async {
            delay(1000)
            10
        }

        val b: Deferred<Int> = async {
            delay(1000)
            20
        }

        val c = a.await() + b.await()

        println("c = $c")
    }

    println("spent time $time")
```
輸出結果:
I/System.out: c = 30
    spent time 1014
    
值得注意的是async為併發,所以總時數不超過2秒

## WithContext
withContext與coroutineScope都會暫停當前block
~~前者可以回傳值~~
前者可以指定CoroutineContext
```kotlin=
private suspend fun doSomethingWithContext(it: Int):Int = withContext(Dispatchers.Default) {
    println("doSomethingWithContext start")
    delay(1000)
    println("doSomethingWithContext end")

    it*it
}

private suspend fun doSomethingWithCoroutineScope(it: Int):Int = coroutineScope {
    println("doSomethingWithCoroutineScope start")
    delay(1000)
    println("doSomethingWithCoroutineScope end")

    it-1000
}

fun main(){
    
    runBlocking {
        val time = measureTimeMillis {
            val x = doSomethingWithContext(100)
            println("x = $x")
            val y = doSomethingWithCoroutineScope(x)
            println("y = $y")
        }
        println("time = $time")
    }
}

```
輸出結果:
I/System.out: doSomethingWithContext start
I/System.out: doSomethingWithContext end
I/System.out: x = 10000
I/System.out: doSomethingWithCoroutineScope start
I/System.out: doSomethingWithCoroutineScope end
    y = 9000
    time = 2024