协程:join() 和 cancelAndJoin() 之间的区别

And*_*Dev 11 kotlin-coroutines

我遵循协程的参考文档(https://kotlinlang.org/docs/reference/coroutines/cancellation-and-timeouts.html),并同时在 Android Studio 上测试示例(好孩子)。

但我对 cancelAndJoin() 方法感到非常困惑。

如果我在示例代码中将“cancelAndJoin”替换为“join”,则日志中没有区别。

这是代码:

fun main() = runBlocking {

    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("job: 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.")

}
Run Code Online (Sandbox Code Playgroud)

在两种情况下(使用 join 或 cancelAndJoin)日志是:

job: I'm sleeping 0 ...
job: I'm sleeping 1 ...
job: I'm sleeping 2 ...
main: I'm tired of waiting!
job: I'm sleeping 3 ...
job: I'm sleeping 4 ...
main: Now I can quit.
Run Code Online (Sandbox Code Playgroud)

有人能解释一下这两种方法有什么区别吗?

这不清楚,因为cancel是“停止作业”,join是“等待完成”,但是两者在一起???我们“停下”并“等待”???

提前致谢:)

iCa*_*ntC 19

这不清楚,因为cancel是“停止作业”,join是“等待完成”,但是两者在一起???我们“停下”并“等待”?

我们写了job.cancel()并不意味着job会立即取消。

当我们写入时job.cancel()进入job瞬态cancelling。这job还没有进入最终状态,进入状态cancelled后才算完全取消。jobcancelled

在此输入图像描述

观察状态转换如何发生,

当我们调用job.cancel()取消过程(completing到 的cancelling转换)时job, . 但我们仍然需要等待,因为job只有当它到达状态时才真正被取消cancelled。因此我们编写job.cancelAndJoin(),其中cancel()启动取消过程jobjoin()确保等待直到job()达到cancelled状态。

请务必查看这篇精彩的文章

注意:该图像是从链接文章本身无耻地复制的


And*_*Dev 3

好吧,我刚刚意识到我的问题很愚蠢!

cancelAndJoin() 等于先cancel() 然后join()。

该代码表明,如果我们不检查作业是否处于活动状态,则无法取消该作业。为此,我们必须使用“isActive”。

像这样:

val startTime = System.currentTimeMillis()
val job = launch(Dispatchers.Default) {
    var nextPrintTime = startTime
    var i = 0
    while (isActive) { // cancellable computation loop
        // print a message twice a second
        if (System.currentTimeMillis() >= nextPrintTime) {
            println("job: 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.")
Run Code Online (Sandbox Code Playgroud)