kotlin: 合作式取消(判断 Job 的状态)
一,例子:cpu密集型任务会使cancel()无效
代码:
//处理按钮点击事件
binding.button1.setOnClickListener {
runBlocking {
val startTime = System.currentTimeMillis()
val job = launch(Dispatchers.Default) {
var nextPrintTime = startTime
var i = 0
while (i < 5) {
if (System.currentTimeMillis() >= nextPrintTime) {
println("I'm sleeping $i")
i++
nextPrintTime += 500
}
}
}
delay(1200)
println("Time to finish")
job.cancelAndJoin()
println("Done")
}
}
运行结果:

看代码运行结果的输出,job 任务并没有按我们设想的那样打印三次就被 cancel。
而是在调用 cancel 方法后,仍然在继续打印,直到 5 次打印完才退出。
这是为什么呢?
这就是因为 job 是一个 CPU 密集型任务,一直抢占着 CPU,
使得 cancel() 命令来不及调度
如何解决这个问题?
我们可以在循环时使用 isActive 属性检查 job 是否处于活跃状态
二,例子,改进,使生效
代码:
//处理按钮点击事件
binding.button2.setOnClickListener {
runBlocking {
val startTime = System.currentTimeMillis()
val job = launch(Dispatchers.Default) {
var nextPrintTime = startTime
var i = 0
while (i < 5 && isActive) {
if (System.currentTimeMillis() >= nextPrintTime) {
println("I'm sleeping $i")
i++
nextPrintTime += 500
}
}
}
delay(1200)
println("Time to finish")
job.cancelAndJoin()
println("Done")
}
}
运行结果:

三,协程合作式取消的三个函数
- ensureActive()[3]
- isActive()[4]
- yield()[5]
代码:
//处理按钮点击事件
binding.button2.setOnClickListener {
runBlocking {
val startTime = System.currentTimeMillis()
val job = launch(Dispatchers.Default) {
var nextPrintTime = startTime
var i = 0
while (i < 5) {
ensureActive()
if (System.currentTimeMillis() >= nextPrintTime) {
println("I'm sleeping $i")
i++
nextPrintTime += 500
}
}
}
delay(1200)
println("Time to finish")
job.cancelAndJoin()
println("Done")
}
}
运行结果:

浙公网安备 33010602011771号