協程作用域

coroutineScope 與 runBlocking

2個suspend函式:

1
2
3
4
5
6
7
8
9
10
  private suspend fun doOne():Int {
    // 1秒
    delay(1000)
    return 10
  }
  private suspend fun doTwo():Int {
    // 2秒
    delay(1000)
    return 20
  }

coroutineScope 非阻塞協程

以下程式碼,二個suspend函式同時執行。
coroutineScope會等待子協程(suspend 函式),執行完畢。

1
2
3
4
5
6
7
8
9
  fun coroutin05() = runTest {
    val startTime = System.currentTimeMillis()
    coroutineScope {
        val one = doOne()
        val two = doTwo()
    }
    val duration = System.currentTimeMillis() - startTime
    println(" in ${duration} ms")
  }
 in 2 ms

runBlocking 阻塞協程

以下程式碼,二個suspend函式逐一執行,doOne()執行完,才輪到doTwo執行()。
所以共執行約2秒鐘左右。
runBlocking會等待子協程(suspend 函式),執行完畢。

1
2
3
4
5
6
7
8
9
  fun coroutin05() = runTest {
    val startTime = System.currentTimeMillis()
    runBlocking {
        val one = doOne()
        val two = doTwo()
    }
    val duration = System.currentTimeMillis() - startTime
    println(" in ${duration} ms")
  }
 in 2009 ms

子協程失敗

  • coroutinScope 子協程失敗,其它子協程會取消
  • supervisorScope 子協程失敗,不會影嚮其它子協程

coroutineScope

job2 拋出Exception(),導致job1被cancel(),不會執行job1 finish。

1
2
3
4
5
6
7
8
9
10
11
12
13
  fun coroutin06() = runTest {
    coroutineScope {
      val job1 = launch {
        delay(400)
        println("job1 finish")
      }
      val job2 = async{
        delay(200)
        println("job2 finish")
        throw IllegalArgumentException()
      }
    }
  }
job2 finish

java.lang.IllegalArgumentException
  at com.example.coroutine.Test01$coroutin06$1$1$job2$1.invokeSuspen

supervisorScope

job2 拋出Exception(),job1仍會執行完畢。

1
2
3
4
5
6
7
8
9
10
11
12
13
  fun coroutin06() = runTest {
    supervisorScope {
      val job1 = launch {
        delay(400)
        println("job1 finish")
      }
      val job2 = async{
        delay(200)
        println("job2 finish")
        throw IllegalArgumentException()
      }
    }
  }
job2 finish
job1 finish

Scope作用域

以下自建Scope作用域,調度器設為預設Dispatchers.Default。
使用scope.launch{},使用的是自建Scope協程。

1
2
3
4
5
6
7
  fun coroutin07() = runBlocking {
    val scope = CoroutineScope(Dispatchers.Default)
    scope.launch {
      delay(1000)
      println("job1")
    }
  }

但執行完卻沒有任何結果,這是為什麼?
runBlocking協程與作用域協程,沒有父子關係,所以runBlocking協程執行完畢就結束,不會等待scope.launch{}協程執行完,才結束。

delay

增加一個delay(大於1000) delay()參數要大於1000,等到scope執行完畢,runBlocking協程才能結束。

1
2
3
4
5
6
7
8
  fun coroutin07() = runBlocking {
    val scope = CoroutineScope(Dispatchers.Default)
    scope.launch {
      delay(1000)
      println("job1")
    }
    delay(2000)
  }
job1

join

runBlocking協程「等待」scope.job完成,runBlocking才能結束。

1
2
3
4
5
6
7
8
  fun coroutin07() = runBlocking {
    val scope = CoroutineScope(Dispatchers.Default)
    val job = scope.launch {
      delay(1000)
      println("job1")
    }
    job.join()
  }
job1

GlobalScope

GlobalScope也是作用域,加上join,runBlocking才會等待GlobalScope執行完畢。

1
2
3
4
5
6
7
8
  @Test
  fun coroutin08() = runBlocking {
    val job = GlobalScope.launch {
      delay(1000)
      println("job1")
    }
    job.join()
  }

results matching ""

    No results matching ""