withContext(NonCancellable): 让挂起函数不被取消

withContext(NonCancellable)可以让挂起函数不被取消。从效果上来看,有点像java中的interrupt打断sleep来中断线程

1. 效果验证

  • 使用 withContext(NonCancellable),代码如下

import kotlinx.coroutines.*

fun main() = runBlocking{



    // # 9
    /**
     * 使用withContext(NonCancellable)后,即使取消,它里面的内容都会执行完,不使用的话,就会只delay后面就不执行了
     */
    val job = launch {
        try {
            repeat(1000) {
                println("job: I'm sleeping $it")
                delay(1000L)

            }
        }finally {
//            println("job: I'm running finally")
//            delay(10L)
//            println("job: And I'v just delayed for 1 sec beca")
            println("job: I'm running finally")
            withContext(NonCancellable){

                delay(1000L)

            }
            println("job: And I'v just delayed for 1 sec beca")

        }
    }

    delay(1300L)
    println("main: I'm tired of waiting!")
    job.cancelAndJoin()
    println("main: Now I can quit.")

    

}

打印日志如下:

job: I'm sleeping 0
job: I'm sleeping 1
main: I'm tired of waiting!
job: I'm running finally
job: And I'v just delayed for 1 sec beca
main: Now I can quit.
  • 不适用withContext(NonCancellable), 代码如下:

import kotlinx.coroutines.*

fun main() = runBlocking{



    // # 9
    /**
     * 使用withContext(NonCancellable)后,即使取消,它里面的内容都会执行完,不使用的话,就会只delay后面就不执行了
     */
    val job = launch {
        try {
            repeat(1000) {
                println("job: I'm sleeping $it")
                delay(1000L)

            }
        }finally {
            println("job: I'm running finally")
            delay(10L)
            println("job: And I'v just delayed for 1 sec beca")
//            println("job: I'm running finally")
//            withContext(NonCancellable){
//
//                delay(1000L)
//
//            }
//            println("job: And I'v just delayed for 1 sec beca")

        }
    }

    delay(1300L)
    println("main: I'm tired of waiting!")
    job.cancelAndJoin()
    println("main: Now I can quit.")



}

日志如下:


job: I'm sleeping 0
job: I'm sleeping 1
main: I'm tired of waiting!
job: I'm running finally
main: Now I can quit.

从日志可以看出,代码被从delay位置打断

2. 为什么说这个打断只是像java中线程的sleep一样呢

验证代码如下:

import kotlinx.coroutines.*

fun main() = runBlocking{

    val job = launch {
        try {
            repeat(1000) {
                println("job: I'm sleeping $it")
                delay(1000L)

            }
        }finally {
//            println("job: I'm running finally")
//            delay(10L)
//            println("job: And I'v just delayed for 1 sec beca")
            println("job: I'm running finally")
//            withContext(NonCancellable){
//                delay(1000L)
//            }
            cpuExecuteTime(5)
            println("job: And I'v just delayed for 1 sec beca")

        }
    }

    delay(1300L)
    println("main: I'm tired of waiting!")
    job.cancelAndJoin()
    println("main: Now I can quit.")



}


/**
 * @param time second
 */
private suspend fun cpuExecuteTime(time:Long){
    var nextPrintTime = System.currentTimeMillis()
    var i = 0
    while (i < time) {
        if (System.currentTimeMillis() >= nextPrintTime) {
            println("cup execute i = ${i++} second")
            nextPrintTime += 1000L
        }
    }

}

打印的日志如下:

job: I'm sleeping 0
job: I'm sleeping 1
main: I'm tired of waiting!
job: I'm running finally
cup execute i = 0 second
cup execute i = 1 second
cup execute i = 2 second
cup execute i = 3 second
cup execute i = 4 second
job: And I'v just delayed for 1 sec beca
main: Now I can quit.

可以看到哪怕是cancel了,cpuExecuteTime这个函数也还在继续执行直到完成,cancel方法并没有起作用。
这里引入了一个cpuExecuteTime的新函数,作用几乎空转一段时间,反正就是保持cpu运行。
因此这里可以得出结论,cancel无法打断这种非delay或者sleep的执行代码。这就有点像java中调用Thread的interrupt打断线程了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值