[英]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.