簡體   English   中英

為什么不能取消kotlin協程?

[英]Why can't kotlin coroutine be canceled?

我預期的結果是 (0, 1) 或 (0, 1, 2),但打印不斷增加的數字而不會停止。 我正在研究協程。 一直在照着這個例子,但是我很好奇,所以寫了代碼,發現了一些奇怪的地方。

class test {
    @Test
    fun test() = runBlocking {
        val startTime = System.currentTimeMillis()
        val job = launch {
            var nextTime = startTime
            var i = 0

            while (isActive) {
                if (System.currentTimeMillis() >= nextTime) {
                    println("${i++}")
                    nextTime += 500L
                }
            }
        }

        delay(1000L)
        println("[main]: tired for wait")
        job.cancelAndJoin()
        println("[main]: finish")
    }
}

---
0
1
2
3
4
5
6
...

但是下面的代碼按預期工作。

class test {
    @Test
    fun test() = runBlocking {
        val startTime = System.currentTimeMillis()
        val job = launch(Dispatchers.Default) {
            var nextTime = startTime
            var i = 0

            while (isActive) {
                if (System.currentTimeMillis() >= nextTime) {
                    println("${i++}")
                    nextTime += 500L
                }
            }
        }

        delay(1000L)
        println("[main]: tired for wait")
        job.cancelAndJoin()
        println("[main]: finish")
    }
}

----
0
1
2
[main]: tired for wait
[main]: finish

我只是添加Dispatchers.Default來啟動。 為什么第一個代碼輸出不是預期的?

這是因為默認情況下runBlocking()創建一個單線程調度器來調度協程。 外協程到達delay()點,它掛起,然后內協程開始執行,但它永遠不會釋放其線程,因此外協程無法恢復。 並且因為外協程永遠不會恢復,所以它不能取消內協程。

為避免此類問題,如果您需要執行非常長的計算,不時調用yield()是個好主意。 它可以釋放線程以供其他協程使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM