4
1

More than 5 years have passed since last update.

Kotlin 1.3のCoroutineのキャンセル②(協力的なキャンセル)

Posted at

検証環境

この記事の内容は、以下の環境で検証しました。

  • Intellij IDEA ULTIMATE 2018.2
  • Kotlin 1.3.0
  • Gradle Projectで作成
  • GradleファイルはKotlinで記述(KotlinでDSL)

準備

詳細は下記の準備を参照してください。
https://qiita.com/naoi/items/8abf2cddfc2cb3802daa

Cancellation is cooperative

前回に引き続き、公式サイトを読み解いていきます。

今回のタイトルは日本語にすると意味がわかりません。
内容を理解すれば、理解できるかもしれません。
早速読み進めます。

Coroutine cancellation is cooperative. A coroutine code has to cooperate to be cancellable.
All the suspending functions in kotlinx.coroutines are cancellable.
They check for cancellation of coroutine and throw CancellationException when cancelled. However, if a coroutine is working in a computation and does not check for cancellation, then it cannot be cancelled, like the following example shows:

訳してみると

コルーチンはキャンセルに処理に対して協力的です。また、コルーチンのコードはキャンセルに対して、協力的でなければなりません。
kotlinx.coroutinesパッケージに存在するすべてのsuspend関数はキャンセルできます。
それらの関数はキャンセル状態かどうかを常にチェックしています。キャンセルが発生するとCancellationException例外が発生します。
しかし、コルーチンで、計算処理の最中などの場合は、キャンセルができません。

なるほど、タイトルの本質は、コルーチンに関する関数は常にキャンセルされているかチェックしているから、キャンセルに対応できている(協力できている)という意味だったんですね。

でも、キャンセル出来ない場合もあるそうで、そのサンプルコードも掲載されているので確認してみます。

fun main() = runBlocking {
    //sampleStart
    val startTime = System.currentTimeMillis()
    val job = launch(Dispatchers.Default) {
        var nextPrintTime = startTime
        var i = 0
        while (i < 5) { // computation loop, just wastes CPU
            // print a message twice a second
            if (System.currentTimeMillis() >= nextPrintTime) {
                println("I'm sleeping ${i++} ...")
                nextPrintTime += 500L
            }
        }
    }
    delay(1300L) // delay a bit
    println("main: I'm tired of waiting!")
    job.cancelAndJoin() // cancels the job and waits for its completion
    println("main: Now I can quit.")
//sampleEnd
}

実行結果

I'm sleeping 0 ...
I'm sleeping 1 ...
I'm sleeping 2 ...
main: I'm tired of waiting!
I'm sleeping 3 ...
I'm sleeping 4 ...
main: Now I can quit.

前回との大きな違いはrepeat関数を使わずにwhile文を使用しているため、キャンセルのチェックが行われていません。while文は確かに通常の計算処理と同じため、キャンセル出来ていない事が確認できます。

公式サイトには、最後にこんな一文が載っています。

Run it to see that it continues to print "I'm sleeping" even after cancellation until the job completes by itself after five iterations.

訳してみると

実行し見ると、コルーチンはキャンセルされているにもかかわらず、ジョブが完了するまで、表示をしているね。

確かにそのとおりです。

まとめ

このブロックで理解できたことは以下のことだと思います。

  • kotlinx.coroutinesパッケージ内の関数はキャンセルをチェックしていること
  • 上記以外はチェックしていないこと
4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1