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

时间:2020-04-09 12:21:05

标签: kotlin-coroutines

我遵循Coroutine(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.")

}

,在2种情况下(使用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.

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

这还不清楚,因为取消是“停止工作”,联接是“等待完成”,但是两者在一起???我们“停止”并“等待” ???

非常感谢:)

2 个答案:

答案 0 :(得分:2)

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

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.")

答案 1 :(得分:0)

不清楚,因为取消是“停止工作”,加入是 “等待完成”,但两者在一起???我们“停止”并 “等待”?

仅仅因为我们写了job.cancel()并不意味着该工作将立即取消。

当我们写job.cancel()时,job进入瞬态取消状态。该job尚未进入最终的完成状态,只有在job进入完成状态后,它才能被视为完全取消。

有关更多详细信息,请查看this